/*
kunpengsecl licensed under the Mulan PSL v2.
You can use this software according to the terms and conditions of
the Mulan PSL v2. You may obtain a copy of Mulan PSL v2 at:
    http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.

Author: wucaijun
Create: 2021-10-08
Description: Using grpc to implement the rasService API.
	1. 2022-01-19	wucaijun
		redefine SendReportRequest parameters and refine some implementations.
	2. 2022-01-28	wucaijun
		fix the problem that grpc occupy all the file handle, use LimitListener
		and getSockNum to auto adjust the max limit of grpc socket handle.
	3. 2022-01-29	wucaijun
		add a new group communication functions to rac, these functions will try
	to use the same grpc socket to enhance performance if possible.

Notice:
	For performance, change the process max file limit and database max connections.
`ulimit -n 200000`			# set in the ras start bash script
`max_connections = 1000`	# in /var/lib/pgsql/data/postgresql.conf and restart
*/

package clientapi

/*
import (
	context "context"
	"crypto/rand"
	"crypto/rsa"
	"crypto/x509"
	"crypto/x509/pkix"
	"encoding/base64"
	"encoding/hex"
	"encoding/json"
	"encoding/pem"
	"io"
	"io/ioutil"
	"math/big"
	"net"
	"os"
	"testing"
	"time"

	"gitee.com/openeuler/kunpengsecl/attestation/common/cryptotools"
	kmsServer "gitee.com/openeuler/kunpengsecl/attestation/kms"
	"gitee.com/openeuler/kunpengsecl/attestation/ras/cache"
	"gitee.com/openeuler/kunpengsecl/attestation/ras/config"
	"gitee.com/openeuler/kunpengsecl/attestation/ras/kcms/kcmstools"
	"gitee.com/openeuler/kunpengsecl/attestation/ras/kcms/kdb"
	"gitee.com/openeuler/kunpengsecl/attestation/ras/trustmgr"
	"github.com/stretchr/testify/assert"
)

const (
	EKpubPEM = `
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAjNq/p49Xwi8UTqq+e+wr
nsXeDfHJjVrtjmAJZvIgrkuYkItllkIINnjPYxKll56kuYVQZoKmQYDMNXN4zWON
BQEko2azkwBdZnkkyFefTpfLY3t6njmO0go318vvrZ2EuPCOBAtWQ1YuxbdD0f+C
haCjLbpGAJJwfpvQnLWLriYstxISEMUoeY6j5XYl4rR84Y3EvNsTDTK/omnUUWUF
TLa9wCAmgcwTZQXakgvsyv/+v1c4yU3rxgn71XqhzYMK3wwzYzxUp5GEg9I5u6Vd
+F5Uys+gK4X5pByIIYwyc/HJYr7yYLTWIeN8Ovg+XOLq/X33CpwNXvf3LMoJCjBH
JwIDAQAB
-----END PUBLIC KEY-----`
	IKpubPEM = `
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAn8CYQqdaTdMxnKp248Fb
UZhxmpSTbb5CA/wUQQ0ARzr0eV3VwzKUhf8mPzkZQDTh36MzGxviBOpk922Gq3Ou
g1OXZ2LG2FPelqQRMvdWY3P/ITzKCoJ+DxlSDAt2zNuXRPnn/TyhXLx8UIAf5Vsx
OjvRxfV/z4r7zcOf33FdI8SuLV3YpNo/pOTJwqv/egV0kxtHDmqI3Vus+KSRjg6g
mlFex7A5TP8axDyLz0nPYP7XLbx1xNQ58VE8Oe51k7qwv8TOE03FVkWkSY25OEH1
2fSx1FasGAEVXVeEugz2W49rLXH4g8DMQ46Q6340J/+oS7+zT1Z0wNDGkqyQD1st
FQIDAQAB
-----END PUBLIC KEY-----`
)

const serverConfig = `
database:
  host: localhost
  name: kunpengsecl
  password: postgres
  port: 5432
  user: postgres
log:
  file: ./logs/ras-log.txt
racconfig:
  digestalgorithm: sha1
  hbduration: 10s
  trustduration: 2m0s
rasconfig:
  authkeyfile: ./ecdsakey.pub
  pcakeycertfile: ""
  pcaprivkeyfile: ""
  restport: 127.0.0.1:40002
  rootkeycertfile: ""
  rootprivkeyfile: ""
  mgrstrategy: "auto"
  serialnumber: 0
  serverport: 127.0.0.1:40001
  onlineduration: 30s
  basevalue-extract-rules:
    manifest:
    - name:
      - 8-0
      - 80000008-1
      type: bios
    - name:
      - boot_aggregate
      - /etc/modprobe.d/tuned.conf
      type: ima
    pcrinfo:
      pcrselection:
      - 1
      - 2
      - 3
      - 4
`
const (
	configFilePath = "./config.yaml"
	BIOSLogPath    = "../../rac/cmd/raagent/binary_bios_measurements"
	IMALogPath     = "../../rac/cmd/raagent/ascii_runtime_measurements"
)

const (
	kcmCert = `
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number: 2 (0x2)
        Signature Algorithm: sha256WithRSAEncryption
        Issuer: C=CN, ST=Shanghai, L=Shanghai, O=Huawei, CN=ca
        Validity
            Not Before: Dec  9 00:36:05 2022 GMT
            Not After : Nov 30 00:36:05 2023 GMT
        Subject: C=CN, ST=Shanghai, L=Shanghai, O=Huawei, CN=kcm
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                RSA Public-Key: (2048 bit)
                Modulus:
                    00:cf:e5:72:98:85:46:34:54:51:fe:bd:f4:3f:7a:
                    24:57:44:36:76:02:75:0a:ff:bf:e2:c4:8f:6f:50:
                    54:d2:6d:3a:13:fa:17:f7:1b:df:9b:6f:2a:22:3f:
                    b2:a4:ad:b7:bc:64:36:fb:69:ec:15:52:b1:ba:b7:
                    6c:2c:5b:89:2b:50:3b:1d:be:a7:4f:91:19:d2:6e:
                    49:47:6b:45:f2:7d:9c:94:fa:f5:d8:86:e6:37:04:
                    8e:aa:06:1e:3e:e2:95:27:9b:f7:f5:e6:34:d7:2f:
                    1e:46:bd:90:89:be:43:0d:cf:c4:91:19:80:26:95:
                    3c:1f:f1:bd:23:01:c3:50:92:69:1a:07:c2:e6:af:
                    07:47:fe:a2:41:04:1c:9a:ca:ed:5d:fc:b4:93:72:
                    c0:ee:58:5b:2a:e8:81:e6:7c:ae:d1:4e:d0:59:14:
                    ea:f6:4f:bc:01:e4:39:af:1b:db:05:01:c3:b2:da:
                    25:f4:86:10:d9:92:81:aa:e5:d6:fd:09:a8:3c:e3:
                    d0:37:df:a9:de:5b:65:7c:f6:90:7c:ff:1b:83:67:
                    47:a5:3f:95:1f:3e:43:70:20:d5:29:0b:30:24:fb:
                    a8:c1:6c:44:99:69:c1:4a:bf:65:b6:83:bf:f3:5c:
                    33:43:11:db:63:ea:01:85:4e:6a:e5:26:20:75:5e:
                    79:23
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Basic Constraints:
                CA:FALSE
            Netscape Comment:
                OpenSSL Generated Certificate
            X509v3 Subject Key Identifier:
                AC:68:E3:D5:5A:64:E6:1B:DB:32:1F:BA:01:5C:6A:ED:08:13:F5:E2
            X509v3 Authority Key Identifier:
                keyid:F7:CC:87:ED:0D:1F:86:8B:C5:34:8E:47:08:47:AA:70:AF:EF:82:A6

    Signature Algorithm: sha256WithRSAEncryption
         a7:af:17:de:eb:7b:32:82:0b:f6:58:c1:15:5a:0a:01:57:81:
         fb:4f:b2:e4:d8:27:27:bb:3e:cf:cd:6f:17:a1:75:25:5e:ec:
         5a:57:8c:79:f3:69:39:54:35:1b:7f:a2:30:74:1d:3d:33:79:
         ce:72:e8:7e:51:f3:e7:fd:80:ab:a1:ec:b4:7c:26:16:a8:09:
         e9:91:d4:b2:7a:ba:a6:ee:73:d8:64:27:13:d9:55:51:33:3c:
         f6:2f:2f:be:27:c6:7a:15:e3:49:f8:5f:c9:50:af:5a:fc:9b:
         fb:fc:f9:09:0e:ba:b7:f3:5a:f3:13:05:2d:56:b9:46:ce:ec:
         ae:b5:66:7b:e3:16:72:27:01:e1:d5:d3:c5:43:66:5f:b1:9c:
         4d:bc:69:df:8a:b2:cc:a9:6d:bc:2d:36:76:ee:ae:20:9a:3d:
         75:a1:ea:f0:58:e6:29:81:68:aa:09:56:23:80:a8:cf:92:9f:
         01:e0:2c:f0:21:c0:63:2d:21:50:e7:d6:c0:8a:1c:f7:50:ba:
         e1:05:f4:96:a7:b7:54:7c:e2:80:0c:de:c6:c7:bd:86:8a:84:
         4b:11:09:79:0e:b4:5c:9d:b2:44:9a:ed:0c:ee:22:3f:f9:e3:
         24:75:2e:44:60:c7:7b:c5:8e:fd:36:8d:60:95:70:54:f2:82:
         4a:5f:f8:50
-----BEGIN CERTIFICATE-----
MIIDmTCCAoGgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBRMQswCQYDVQQGEwJDTjER
MA8GA1UECAwIU2hhbmdoYWkxETAPBgNVBAcMCFNoYW5naGFpMQ8wDQYDVQQKDAZI
dWF3ZWkxCzAJBgNVBAMMAmNhMB4XDTIyMTIwOTAwMzYwNVoXDTIzMTEzMDAwMzYw
NVowUjELMAkGA1UEBhMCQ04xETAPBgNVBAgMCFNoYW5naGFpMREwDwYDVQQHDAhT
aGFuZ2hhaTEPMA0GA1UECgwGSHVhd2VpMQwwCgYDVQQDDANrY20wggEiMA0GCSqG
SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDP5XKYhUY0VFH+vfQ/eiRXRDZ2AnUK/7/i
xI9vUFTSbToT+hf3G9+bbyoiP7Kkrbe8ZDb7aewVUrG6t2wsW4krUDsdvqdPkRnS
bklHa0XyfZyU+vXYhuY3BI6qBh4+4pUnm/f15jTXLx5GvZCJvkMNz8SRGYAmlTwf
8b0jAcNQkmkaB8LmrwdH/qJBBByayu1d/LSTcsDuWFsq6IHmfK7RTtBZFOr2T7wB
5DmvG9sFAcOy2iX0hhDZkoGq5db9Cag849A336neW2V89pB8/xuDZ0elP5UfPkNw
INUpCzAk+6jBbESZacFKv2W2g7/zXDNDEdtj6gGFTmrlJiB1XnkjAgMBAAGjezB5
MAkGA1UdEwQCMAAwLAYJYIZIAYb4QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENl
cnRpZmljYXRlMB0GA1UdDgQWBBSsaOPVWmTmG9syH7oBXGrtCBP14jAfBgNVHSME
GDAWgBT3zIftDR+Gi8U0jkcIR6pwr++CpjANBgkqhkiG9w0BAQsFAAOCAQEAp68X
3ut7MoIL9ljBFVoKAVeB+0+y5NgnJ7s+z81vF6F1JV7sWleMefNpOVQ1G3+iMHQd
PTN5znLoflHz5/2Aq6HstHwmFqgJ6ZHUsnq6pu5z2GQnE9lVUTM89i8vvifGehXj
SfhfyVCvWvyb+/z5CQ66t/Na8xMFLVa5Rs7srrVme+MWcicB4dXTxUNmX7GcTbxp
34qyzKltvC02du6uIJo9daHq8FjmKYFoqglWI4Coz5KfAeAs8CHAYy0hUOfWwIoc
91C64QX0lqe3VHzigAzexse9hoqESxEJeQ60XJ2yRJrtDO4iP/njJHUuRGDHe8WO
/TaNYJVwVPKCSl/4UA==
-----END CERTIFICATE-----`
)

const (
	command                = 0x00008003
	constDNS               = "user=postgres password=postgres dbname=kunpengsecl host=localhost port=5432 sslmode=disable"
	constSaveKTACertFailed = "save KTA Cert failed %v"
	constsavekeyinfofailed = "save key information fail %v"
	constgetcachefailed    = "get cache by deviceId failed :%v"
	fileMod                = 0755
	keyMod                 = 0600
)

var (
	byteTable = []int{
		48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
		80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108,
		109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122}
	taId                = "taId"
	keyId               = "keyId"
	hostKeyId           = "hostKeyId"
	account             = "account"
	password            = "password"
	deviceId      int64 = 1238263726351263121
	cipherMessage       = "89Kl9gkvWImjh5CUsADSbmFyDb7s5q+voUf2ym4u6dc="
	ktaId               = "ktaId"
	ik                  = "IK"
	testCases1          = []time.Duration{time.Second, time.Second * 3, time.Millisecond * 10}
)

var (
	IKName = []byte{
		0x00, 0x0b, 0x25, 0x7f, 0x26, 0x0b, 0x02, 0x18, 0xf2, 0x15, 0xda, 0x02, 0xf9, 0xba, 0x7c, 0xf2, 0x68,
		0x15, 0x47, 0x80, 0x47, 0xa9, 0xaf, 0x60, 0x04, 0x88, 0x8e, 0x57, 0xfb, 0x34, 0x02, 0xd0, 0xf3, 0xf0}
	testquote = []byte{
		0xff, 0x54, 0x43, 0x47, 0x80, 0x18, 0x00, 0x22, 0x00, 0x0b, 0x12, 0x66, 0xfc, 0x6a, 0x0d, 0xdf, 0x97,
		0xb2, 0x9d, 0x01, 0x5d, 0xa0, 0xba, 0x65, 0x88, 0x02, 0x46, 0xfd, 0x6a, 0x6c, 0x07, 0xd4, 0x9f, 0x4a,
		0xd2, 0x15, 0xd8, 0x4c, 0x77, 0xf2, 0x74, 0x5d, 0x00, 0x20, 0x8f, 0xf2, 0x28, 0xf1, 0xbe, 0xe4, 0x63,
		0x0f, 0x6d, 0xe3, 0x52, 0xf0, 0xa0, 0x17, 0x8d, 0xc8, 0xd4, 0x48, 0x15, 0x06, 0xc1, 0x67, 0x51, 0xcd,
		0x50, 0x36, 0x87, 0xa5, 0x5f, 0xcf, 0xb8, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x00,
		0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x20, 0x17, 0x06, 0x19, 0x00, 0x16, 0x36, 0x36, 0x00,
		0x00, 0x00, 0x01, 0x00, 0x04, 0x03, 0xff, 0xff, 0xff, 0x00, 0x20, 0x3f, 0x27, 0x08, 0x3e, 0x20, 0xdb,
		0x7c, 0x0b, 0xf0, 0xe3, 0x16, 0x21, 0x19, 0x00, 0xa9, 0x0a, 0x53, 0xe9, 0x9e, 0xf1, 0x2a, 0x68, 0x62,
		0x2e, 0x89, 0x79, 0x27, 0x93, 0x59, 0x88, 0x03, 0xd2}
	testsignature = []byte{
		0x7b, 0x22, 0x41, 0x6c, 0x67, 0x22, 0x3a, 0x32, 0x30, 0x2c, 0x22, 0x52, 0x53, 0x41, 0x22, 0x3a, 0x7b,
		0x22, 0x48, 0x61, 0x73, 0x68, 0x41, 0x6c, 0x67, 0x22, 0x3a, 0x31, 0x31, 0x2c, 0x22, 0x53, 0x69, 0x67,
		0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, 0x3a, 0x22, 0x47, 0x67, 0x30, 0x70, 0x78, 0x32, 0x47, 0x66,
		0x73, 0x38, 0x56, 0x32, 0x2b, 0x43, 0x77, 0x42, 0x2b, 0x6c, 0x55, 0x35, 0x78, 0x5a, 0x31, 0x55, 0x54,
		0x51, 0x6d, 0x36, 0x74, 0x55, 0x6e, 0x45, 0x43, 0x53, 0x44, 0x34, 0x59, 0x4b, 0x35, 0x34, 0x6a, 0x4e,
		0x32, 0x46, 0x49, 0x31, 0x52, 0x78, 0x4f, 0x6a, 0x58, 0x44, 0x79, 0x50, 0x63, 0x36, 0x4d, 0x47, 0x6e,
		0x67, 0x6e, 0x4c, 0x68, 0x2f, 0x4c, 0x31, 0x31, 0x46, 0x4e, 0x69, 0x6e, 0x49, 0x42, 0x30, 0x61, 0x55,
		0x53, 0x75, 0x63, 0x2f, 0x63, 0x6e, 0x76, 0x41, 0x52, 0x45, 0x41, 0x4a, 0x52, 0x50, 0x65, 0x39, 0x2b,
		0x42, 0x69, 0x50, 0x30, 0x69, 0x66, 0x6c, 0x53, 0x51, 0x45, 0x48, 0x6e, 0x63, 0x4d, 0x57, 0x30, 0x43,
		0x6d, 0x47, 0x6a, 0x42, 0x30, 0x6d, 0x30, 0x75, 0x43, 0x65, 0x77, 0x70, 0x63, 0x4d, 0x50, 0x73, 0x43,
		0x44, 0x4f, 0x52, 0x78, 0x4b, 0x4b, 0x2b, 0x4d, 0x4c, 0x35, 0x54, 0x38, 0x75, 0x4c, 0x4e, 0x65, 0x6d,
		0x4b, 0x58, 0x45, 0x50, 0x4f, 0x69, 0x36, 0x4c, 0x77, 0x49, 0x6b, 0x39, 0x38, 0x63, 0x6b, 0x64, 0x61,
		0x4f, 0x65, 0x76, 0x58, 0x39, 0x42, 0x62, 0x4c, 0x5a, 0x4e, 0x77, 0x7a, 0x51, 0x35, 0x4d, 0x42, 0x73,
		0x33, 0x6e, 0x50, 0x50, 0x48, 0x6c, 0x47, 0x39, 0x44, 0x70, 0x72, 0x68, 0x63, 0x6b, 0x67, 0x73, 0x44,
		0x48, 0x43, 0x75, 0x73, 0x72, 0x43, 0x34, 0x4b, 0x71, 0x5a, 0x48, 0x2f, 0x32, 0x39, 0x52, 0x54, 0x78,
		0x70, 0x58, 0x6d, 0x65, 0x39, 0x43, 0x4e, 0x50, 0x43, 0x6f, 0x6b, 0x61, 0x52, 0x6f, 0x70, 0x31, 0x77,
		0x77, 0x33, 0x54, 0x4e, 0x39, 0x79, 0x72, 0x5a, 0x68, 0x6d, 0x38, 0x55, 0x47, 0x47, 0x4b, 0x48, 0x66,
		0x55, 0x33, 0x59, 0x42, 0x63, 0x66, 0x77, 0x32, 0x57, 0x6f, 0x78, 0x36, 0x50, 0x58, 0x72, 0x61, 0x7a,
		0x48, 0x37, 0x52, 0x6a, 0x72, 0x66, 0x4b, 0x57, 0x62, 0x59, 0x69, 0x4b, 0x56, 0x79, 0x48, 0x67, 0x36,
		0x56, 0x4e, 0x45, 0x32, 0x4e, 0x4f, 0x75, 0x6d, 0x41, 0x76, 0x36, 0x54, 0x30, 0x58, 0x48, 0x78, 0x2b,
		0x39, 0x39, 0x53, 0x71, 0x6f, 0x58, 0x30, 0x6c, 0x6d, 0x39, 0x4a, 0x7a, 0x30, 0x39, 0x77, 0x53, 0x74,
		0x54, 0x59, 0x35, 0x33, 0x71, 0x66, 0x6d, 0x4e, 0x32, 0x31, 0x36, 0x41, 0x69, 0x32, 0x73, 0x57, 0x39,
		0x72, 0x66, 0x2b, 0x74, 0x70, 0x7a, 0x7a, 0x6a, 0x6a, 0x36, 0x67, 0x3d, 0x3d, 0x22, 0x7d, 0x2c, 0x22,
		0x45, 0x43, 0x43, 0x22, 0x3a, 0x6e, 0x75, 0x6c, 0x6c, 0x7d}
	testpcr = []byte{
		0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
		0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
		0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x20, 0x73, 0x68, 0x61, 0x31, 0x20, 0x30, 0x30, 0x0a, 0x30, 0x30,
		0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
		0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
		0x30, 0x30, 0x30, 0x30, 0x20, 0x73, 0x68, 0x61, 0x31, 0x20, 0x30, 0x31, 0x0a, 0x30, 0x30, 0x30, 0x30,
		0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
		0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
		0x30, 0x30, 0x20, 0x73, 0x68, 0x61, 0x31, 0x20, 0x30, 0x32, 0x0a, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
		0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
		0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
		0x20, 0x73, 0x68, 0x61, 0x31, 0x20, 0x30, 0x33, 0x0a, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
		0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
		0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x20, 0x73,
		0x68, 0x61, 0x31, 0x20, 0x30, 0x34, 0x0a, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
		0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
		0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x20, 0x73, 0x68, 0x61,
		0x31, 0x20, 0x30, 0x35, 0x0a, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
		0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
		0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x20, 0x73, 0x68, 0x61, 0x31, 0x20,
		0x30, 0x36, 0x0a, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
		0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
		0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x20, 0x73, 0x68, 0x61, 0x31, 0x20, 0x30, 0x37,
		0x0a, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
		0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
		0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x20, 0x73, 0x68, 0x61, 0x31, 0x20, 0x30, 0x38, 0x0a, 0x30,
		0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
		0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
		0x30, 0x30, 0x30, 0x30, 0x30, 0x20, 0x73, 0x68, 0x61, 0x31, 0x20, 0x30, 0x39, 0x0a, 0x30, 0x30, 0x30,
		0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
		0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
		0x30, 0x30, 0x30, 0x20, 0x73, 0x68, 0x61, 0x31, 0x20, 0x31, 0x30, 0x0a, 0x30, 0x30, 0x30, 0x30, 0x30,
		0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
		0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
		0x30, 0x20, 0x73, 0x68, 0x61, 0x31, 0x20, 0x31, 0x31, 0x0a, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
		0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
		0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x20,
		0x73, 0x68, 0x61, 0x31, 0x20, 0x31, 0x32, 0x0a, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
		0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
		0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x20, 0x73, 0x68,
		0x61, 0x31, 0x20, 0x31, 0x33, 0x0a, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
		0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
		0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x20, 0x73, 0x68, 0x61, 0x31,
		0x20, 0x31, 0x34, 0x0a, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
		0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
		0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x20, 0x73, 0x68, 0x61, 0x31, 0x20, 0x31,
		0x35, 0x0a, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
		0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
		0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x20, 0x73, 0x68, 0x61, 0x31, 0x20, 0x31, 0x36, 0x0a,
		0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
		0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
		0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x20, 0x73, 0x68, 0x61, 0x31, 0x20, 0x31, 0x37, 0x0a, 0x66, 0x66,
		0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
		0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
		0x66, 0x66, 0x66, 0x66, 0x20, 0x73, 0x68, 0x61, 0x31, 0x20, 0x31, 0x38, 0x0a, 0x66, 0x66, 0x66, 0x66,
		0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
		0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
		0x66, 0x66, 0x20, 0x73, 0x68, 0x61, 0x31, 0x20, 0x31, 0x39, 0x0a, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
		0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
		0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
		0x20, 0x73, 0x68, 0x61, 0x31, 0x20, 0x32, 0x30, 0x0a, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
		0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
		0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x20, 0x73,
		0x68, 0x61, 0x31, 0x20, 0x32, 0x31, 0x0a, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
		0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
		0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x20, 0x73, 0x68, 0x61,
		0x31, 0x20, 0x32, 0x32, 0x0a, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
		0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
		0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x20, 0x73, 0x68, 0x61, 0x31, 0x20,
		0x32, 0x33, 0x0a}
	rootcert = []byte{
		0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46,
		0x49, 0x43, 0x41, 0x54, 0x45, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x0a, 0x4d, 0x49, 0x49, 0x44, 0x67, 0x7a,
		0x43, 0x43, 0x41, 0x6d, 0x75, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x55, 0x51, 0x6c, 0x33,
		0x59, 0x56, 0x61, 0x5a, 0x50, 0x53, 0x72, 0x41, 0x62, 0x49, 0x45, 0x7a, 0x55, 0x66, 0x6a, 0x4d, 0x33,
		0x47, 0x5a, 0x37, 0x4b, 0x4a, 0x44, 0x41, 0x77, 0x44, 0x51, 0x59, 0x4a, 0x4b, 0x6f, 0x5a, 0x49, 0x68,
		0x76, 0x63, 0x4e, 0x41, 0x51, 0x45, 0x4c, 0x0a, 0x42, 0x51, 0x41, 0x77, 0x55, 0x54, 0x45, 0x4c, 0x4d,
		0x41, 0x6b, 0x47, 0x41, 0x31, 0x55, 0x45, 0x42, 0x68, 0x4d, 0x43, 0x51, 0x30, 0x34, 0x78, 0x45, 0x54,
		0x41, 0x50, 0x42, 0x67, 0x4e, 0x56, 0x42, 0x41, 0x67, 0x4d, 0x43, 0x46, 0x4e, 0x6f, 0x59, 0x57, 0x35,
		0x6e, 0x61, 0x47, 0x46, 0x70, 0x4d, 0x52, 0x45, 0x77, 0x44, 0x77, 0x59, 0x44, 0x56, 0x51, 0x51, 0x48,
		0x44, 0x41, 0x68, 0x54, 0x0a, 0x61, 0x47, 0x46, 0x75, 0x5a, 0x32, 0x68, 0x68, 0x61, 0x54, 0x45, 0x50,
		0x4d, 0x41, 0x30, 0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x67, 0x77, 0x47, 0x53, 0x48, 0x56, 0x68, 0x64,
		0x32, 0x56, 0x70, 0x4d, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, 0x56, 0x51, 0x51, 0x44, 0x44, 0x41,
		0x4a, 0x6a, 0x59, 0x54, 0x41, 0x65, 0x46, 0x77, 0x30, 0x79, 0x4d, 0x6a, 0x45, 0x78, 0x4d, 0x6a, 0x55,
		0x77, 0x0a, 0x4d, 0x7a, 0x51, 0x31, 0x4e, 0x44, 0x68, 0x61, 0x46, 0x77, 0x30, 0x79, 0x4d, 0x7a, 0x45,
		0x78, 0x4d, 0x54, 0x59, 0x77, 0x4d, 0x7a, 0x51, 0x31, 0x4e, 0x44, 0x68, 0x61, 0x4d, 0x46, 0x45, 0x78,
		0x43, 0x7a, 0x41, 0x4a, 0x42, 0x67, 0x4e, 0x56, 0x42, 0x41, 0x59, 0x54, 0x41, 0x6b, 0x4e, 0x4f, 0x4d,
		0x52, 0x45, 0x77, 0x44, 0x77, 0x59, 0x44, 0x56, 0x51, 0x51, 0x49, 0x44, 0x41, 0x68, 0x54, 0x0a, 0x61,
		0x47, 0x46, 0x75, 0x5a, 0x32, 0x68, 0x68, 0x61, 0x54, 0x45, 0x52, 0x4d, 0x41, 0x38, 0x47, 0x41, 0x31,
		0x55, 0x45, 0x42, 0x77, 0x77, 0x49, 0x55, 0x32, 0x68, 0x68, 0x62, 0x6d, 0x64, 0x6f, 0x59, 0x57, 0x6b,
		0x78, 0x44, 0x7a, 0x41, 0x4e, 0x42, 0x67, 0x4e, 0x56, 0x42, 0x41, 0x6f, 0x4d, 0x42, 0x6b, 0x68, 0x31,
		0x59, 0x58, 0x64, 0x6c, 0x61, 0x54, 0x45, 0x4c, 0x4d, 0x41, 0x6b, 0x47, 0x0a, 0x41, 0x31, 0x55, 0x45,
		0x41, 0x77, 0x77, 0x43, 0x59, 0x32, 0x45, 0x77, 0x67, 0x67, 0x45, 0x69, 0x4d, 0x41, 0x30, 0x47, 0x43,
		0x53, 0x71, 0x47, 0x53, 0x49, 0x62, 0x33, 0x44, 0x51, 0x45, 0x42, 0x41, 0x51, 0x55, 0x41, 0x41, 0x34,
		0x49, 0x42, 0x44, 0x77, 0x41, 0x77, 0x67, 0x67, 0x45, 0x4b, 0x41, 0x6f, 0x49, 0x42, 0x41, 0x51, 0x43,
		0x78, 0x32, 0x44, 0x37, 0x50, 0x72, 0x75, 0x39, 0x49, 0x0a, 0x52, 0x78, 0x37, 0x6d, 0x4d, 0x69, 0x35,
		0x39, 0x4a, 0x5a, 0x37, 0x77, 0x48, 0x7a, 0x33, 0x70, 0x44, 0x38, 0x54, 0x4b, 0x58, 0x36, 0x34, 0x61,
		0x78, 0x42, 0x64, 0x70, 0x4a, 0x52, 0x47, 0x57, 0x35, 0x33, 0x79, 0x74, 0x78, 0x48, 0x74, 0x30, 0x50,
		0x6d, 0x35, 0x70, 0x62, 0x73, 0x2b, 0x55, 0x54, 0x58, 0x63, 0x58, 0x47, 0x6d, 0x6c, 0x75, 0x42, 0x53,
		0x76, 0x72, 0x6a, 0x68, 0x65, 0x75, 0x0a, 0x2b, 0x74, 0x4a, 0x47, 0x67, 0x76, 0x73, 0x74, 0x49, 0x69,
		0x63, 0x4b, 0x37, 0x6d, 0x69, 0x65, 0x35, 0x68, 0x39, 0x4e, 0x50, 0x41, 0x55, 0x67, 0x5a, 0x58, 0x6f,
		0x65, 0x46, 0x68, 0x5a, 0x2b, 0x4f, 0x41, 0x72, 0x59, 0x65, 0x38, 0x59, 0x39, 0x74, 0x47, 0x4f, 0x61,
		0x70, 0x6d, 0x67, 0x4a, 0x5a, 0x36, 0x39, 0x68, 0x75, 0x4c, 0x47, 0x77, 0x32, 0x42, 0x45, 0x70, 0x4d,
		0x65, 0x42, 0x63, 0x0a, 0x56, 0x56, 0x76, 0x36, 0x51, 0x41, 0x67, 0x45, 0x6e, 0x38, 0x66, 0x4c, 0x4a,
		0x47, 0x36, 0x4c, 0x75, 0x72, 0x32, 0x71, 0x78, 0x32, 0x39, 0x72, 0x6a, 0x42, 0x57, 0x54, 0x4d, 0x74,
		0x65, 0x6a, 0x6c, 0x47, 0x6f, 0x72, 0x53, 0x46, 0x58, 0x46, 0x36, 0x56, 0x58, 0x55, 0x34, 0x43, 0x51,
		0x66, 0x6b, 0x6a, 0x75, 0x69, 0x6b, 0x4c, 0x4f, 0x32, 0x59, 0x70, 0x6e, 0x6a, 0x4e, 0x2b, 0x64, 0x51,
		0x0a, 0x6c, 0x45, 0x42, 0x64, 0x48, 0x58, 0x7a, 0x64, 0x53, 0x7a, 0x56, 0x37, 0x73, 0x76, 0x50, 0x32,
		0x4b, 0x32, 0x66, 0x44, 0x35, 0x36, 0x58, 0x53, 0x79, 0x65, 0x2b, 0x37, 0x59, 0x36, 0x67, 0x65, 0x72,
		0x37, 0x48, 0x2f, 0x4a, 0x6d, 0x49, 0x51, 0x65, 0x56, 0x49, 0x6d, 0x63, 0x5a, 0x6b, 0x69, 0x78, 0x76,
		0x4c, 0x34, 0x44, 0x6f, 0x4f, 0x4a, 0x70, 0x6c, 0x69, 0x4c, 0x48, 0x57, 0x38, 0x75, 0x0a, 0x76, 0x59,
		0x65, 0x6d, 0x55, 0x6b, 0x77, 0x35, 0x79, 0x4b, 0x4d, 0x6d, 0x2f, 0x6b, 0x57, 0x6f, 0x37, 0x73, 0x41,
		0x72, 0x48, 0x50, 0x78, 0x56, 0x7a, 0x38, 0x6e, 0x4a, 0x4e, 0x77, 0x32, 0x42, 0x43, 0x38, 0x5a, 0x75,
		0x57, 0x65, 0x77, 0x62, 0x63, 0x58, 0x49, 0x55, 0x52, 0x71, 0x32, 0x4b, 0x7a, 0x73, 0x54, 0x76, 0x69,
		0x49, 0x34, 0x41, 0x33, 0x77, 0x33, 0x69, 0x4b, 0x53, 0x6e, 0x57, 0x0a, 0x77, 0x42, 0x56, 0x74, 0x64,
		0x6f, 0x46, 0x6f, 0x6d, 0x42, 0x44, 0x56, 0x41, 0x67, 0x4d, 0x42, 0x41, 0x41, 0x47, 0x6a, 0x55, 0x7a,
		0x42, 0x52, 0x4d, 0x42, 0x30, 0x47, 0x41, 0x31, 0x55, 0x64, 0x44, 0x67, 0x51, 0x57, 0x42, 0x42, 0x54,
		0x54, 0x56, 0x49, 0x70, 0x4c, 0x77, 0x6d, 0x53, 0x55, 0x76, 0x35, 0x37, 0x35, 0x53, 0x6f, 0x6a, 0x48,
		0x36, 0x65, 0x49, 0x51, 0x45, 0x41, 0x66, 0x4f, 0x0a, 0x6e, 0x7a, 0x41, 0x66, 0x42, 0x67, 0x4e, 0x56,
		0x48, 0x53, 0x4d, 0x45, 0x47, 0x44, 0x41, 0x57, 0x67, 0x42, 0x54, 0x54, 0x56, 0x49, 0x70, 0x4c, 0x77,
		0x6d, 0x53, 0x55, 0x76, 0x35, 0x37, 0x35, 0x53, 0x6f, 0x6a, 0x48, 0x36, 0x65, 0x49, 0x51, 0x45, 0x41,
		0x66, 0x4f, 0x6e, 0x7a, 0x41, 0x50, 0x42, 0x67, 0x4e, 0x56, 0x48, 0x52, 0x4d, 0x42, 0x41, 0x66, 0x38,
		0x45, 0x42, 0x54, 0x41, 0x44, 0x0a, 0x41, 0x51, 0x48, 0x2f, 0x4d, 0x41, 0x30, 0x47, 0x43, 0x53, 0x71,
		0x47, 0x53, 0x49, 0x62, 0x33, 0x44, 0x51, 0x45, 0x42, 0x43, 0x77, 0x55, 0x41, 0x41, 0x34, 0x49, 0x42,
		0x41, 0x51, 0x43, 0x70, 0x68, 0x47, 0x42, 0x75, 0x49, 0x47, 0x35, 0x48, 0x75, 0x6c, 0x36, 0x64, 0x58,
		0x38, 0x66, 0x4e, 0x64, 0x2b, 0x6b, 0x7a, 0x72, 0x77, 0x76, 0x6b, 0x61, 0x54, 0x54, 0x48, 0x6e, 0x4c,
		0x6c, 0x64, 0x0a, 0x6b, 0x45, 0x69, 0x54, 0x59, 0x41, 0x42, 0x4f, 0x71, 0x51, 0x54, 0x65, 0x34, 0x6e,
		0x65, 0x2f, 0x53, 0x44, 0x59, 0x43, 0x65, 0x47, 0x37, 0x30, 0x38, 0x56, 0x6a, 0x49, 0x65, 0x53, 0x53,
		0x50, 0x46, 0x73, 0x66, 0x38, 0x4e, 0x50, 0x58, 0x63, 0x58, 0x31, 0x56, 0x58, 0x46, 0x70, 0x4a, 0x46,
		0x47, 0x57, 0x67, 0x56, 0x53, 0x4d, 0x45, 0x51, 0x70, 0x69, 0x73, 0x45, 0x52, 0x37, 0x57, 0x38, 0x0a,
		0x66, 0x2b, 0x38, 0x79, 0x30, 0x41, 0x4b, 0x62, 0x75, 0x65, 0x4e, 0x73, 0x37, 0x71, 0x6b, 0x30, 0x45,
		0x7a, 0x5a, 0x78, 0x5a, 0x37, 0x38, 0x51, 0x61, 0x71, 0x6f, 0x49, 0x50, 0x43, 0x68, 0x64, 0x70, 0x73,
		0x38, 0x66, 0x43, 0x30, 0x78, 0x67, 0x35, 0x47, 0x4d, 0x31, 0x76, 0x44, 0x38, 0x2f, 0x63, 0x74, 0x41,
		0x77, 0x52, 0x4a, 0x61, 0x4b, 0x6e, 0x46, 0x66, 0x4d, 0x52, 0x47, 0x74, 0x5a, 0x0a, 0x34, 0x46, 0x66,
		0x42, 0x64, 0x52, 0x57, 0x4a, 0x6a, 0x57, 0x43, 0x46, 0x31, 0x51, 0x4d, 0x50, 0x41, 0x67, 0x4e, 0x51,
		0x6a, 0x4a, 0x59, 0x66, 0x36, 0x6e, 0x4d, 0x58, 0x74, 0x35, 0x63, 0x6d, 0x34, 0x31, 0x6a, 0x69, 0x6a,
		0x41, 0x4f, 0x65, 0x58, 0x6a, 0x31, 0x4f, 0x4c, 0x61, 0x4f, 0x38, 0x4d, 0x64, 0x34, 0x6b, 0x65, 0x33,
		0x6a, 0x4f, 0x58, 0x54, 0x37, 0x5a, 0x4b, 0x30, 0x59, 0x45, 0x0a, 0x31, 0x73, 0x73, 0x57, 0x6d, 0x68,
		0x61, 0x66, 0x57, 0x30, 0x33, 0x32, 0x45, 0x33, 0x6e, 0x6f, 0x4e, 0x71, 0x44, 0x35, 0x6c, 0x68, 0x64,
		0x6a, 0x6d, 0x33, 0x5a, 0x64, 0x61, 0x2b, 0x72, 0x47, 0x6a, 0x69, 0x57, 0x30, 0x52, 0x48, 0x64, 0x79,
		0x56, 0x39, 0x37, 0x41, 0x66, 0x63, 0x44, 0x42, 0x55, 0x54, 0x74, 0x31, 0x74, 0x50, 0x38, 0x6e, 0x35,
		0x30, 0x46, 0x66, 0x51, 0x79, 0x61, 0x68, 0x0a, 0x4b, 0x75, 0x77, 0x52, 0x4d, 0x76, 0x46, 0x35, 0x4b,
		0x70, 0x68, 0x44, 0x48, 0x34, 0x6c, 0x4b, 0x61, 0x68, 0x79, 0x78, 0x6a, 0x48, 0x71, 0x66, 0x4d, 0x4e,
		0x68, 0x68, 0x73, 0x79, 0x72, 0x2f, 0x44, 0x55, 0x4e, 0x4d, 0x64, 0x78, 0x73, 0x39, 0x73, 0x53, 0x61,
		0x36, 0x79, 0x57, 0x74, 0x75, 0x42, 0x33, 0x73, 0x48, 0x0a, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x45, 0x4e,
		0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2d, 0x2d, 0x2d, 0x2d,
		0x2d, 0x0a}
	ktacert = []byte{
		0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x3a, 0x0a, 0x20, 0x20, 0x20, 0x20,
		0x44, 0x61, 0x74, 0x61, 0x3a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x56, 0x65, 0x72,
		0x73, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x33, 0x20, 0x28, 0x30, 0x78, 0x32, 0x29, 0x0a, 0x20, 0x20, 0x20,
		0x20, 0x20, 0x20, 0x20, 0x20, 0x53, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x20, 0x4e, 0x75, 0x6d, 0x62, 0x65,
		0x72, 0x3a, 0x20, 0x31, 0x20, 0x28, 0x30, 0x78, 0x31, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
		0x20, 0x20, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x20, 0x41, 0x6c, 0x67, 0x6f, 0x72,
		0x69, 0x74, 0x68, 0x6d, 0x3a, 0x20, 0x73, 0x68, 0x61, 0x32, 0x35, 0x36, 0x57, 0x69, 0x74, 0x68, 0x52,
		0x53, 0x41, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x20, 0x20, 0x20, 0x20,
		0x20, 0x20, 0x20, 0x20, 0x49, 0x73, 0x73, 0x75, 0x65, 0x72, 0x3a, 0x20, 0x43, 0x3d, 0x43, 0x4e, 0x2c,
		0x20, 0x53, 0x54, 0x3d, 0x53, 0x68, 0x61, 0x6e, 0x67, 0x68, 0x61, 0x69, 0x2c, 0x20, 0x4c, 0x3d, 0x53,
		0x68, 0x61, 0x6e, 0x67, 0x68, 0x61, 0x69, 0x2c, 0x20, 0x4f, 0x3d, 0x48, 0x75, 0x61, 0x77, 0x65, 0x69,
		0x2c, 0x20, 0x43, 0x4e, 0x3d, 0x63, 0x61, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x56,
		0x61, 0x6c, 0x69, 0x64, 0x69, 0x74, 0x79, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
		0x20, 0x20, 0x20, 0x4e, 0x6f, 0x74, 0x20, 0x42, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x3a, 0x20, 0x4e, 0x6f,
		0x76, 0x20, 0x32, 0x35, 0x20, 0x30, 0x33, 0x3a, 0x34, 0x35, 0x3a, 0x34, 0x38, 0x20, 0x32, 0x30, 0x32,
		0x32, 0x20, 0x47, 0x4d, 0x54, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
		0x20, 0x4e, 0x6f, 0x74, 0x20, 0x41, 0x66, 0x74, 0x65, 0x72, 0x20, 0x3a, 0x20, 0x4e, 0x6f, 0x76, 0x20,
		0x31, 0x36, 0x20, 0x30, 0x33, 0x3a, 0x34, 0x35, 0x3a, 0x34, 0x38, 0x20, 0x32, 0x30, 0x32, 0x33, 0x20,
		0x47, 0x4d, 0x54, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x53, 0x75, 0x62, 0x6a, 0x65,
		0x63, 0x74, 0x3a, 0x20, 0x43, 0x3d, 0x43, 0x4e, 0x2c, 0x20, 0x53, 0x54, 0x3d, 0x53, 0x68, 0x61, 0x6e,
		0x67, 0x68, 0x61, 0x69, 0x2c, 0x20, 0x4c, 0x3d, 0x53, 0x68, 0x61, 0x6e, 0x67, 0x68, 0x61, 0x69, 0x2c,
		0x20, 0x4f, 0x3d, 0x48, 0x75, 0x61, 0x77, 0x65, 0x69, 0x2c, 0x20, 0x43, 0x4e, 0x3d, 0x6b, 0x74, 0x61,
		0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20,
		0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20, 0x4b, 0x65, 0x79, 0x20, 0x49, 0x6e, 0x66, 0x6f, 0x3a, 0x0a,
		0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x50, 0x75, 0x62, 0x6c, 0x69,
		0x63, 0x20, 0x4b, 0x65, 0x79, 0x20, 0x41, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x3a, 0x20,
		0x72, 0x73, 0x61, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x20, 0x20, 0x20,
		0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x52, 0x53, 0x41, 0x20,
		0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x2d, 0x4b, 0x65, 0x79, 0x3a, 0x20, 0x28, 0x32, 0x30, 0x34, 0x38,
		0x20, 0x62, 0x69, 0x74, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
		0x20, 0x20, 0x20, 0x20, 0x20, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x75, 0x73, 0x3a, 0x0a, 0x20, 0x20, 0x20,
		0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
		0x30, 0x30, 0x3a, 0x64, 0x30, 0x3a, 0x35, 0x38, 0x3a, 0x61, 0x39, 0x3a, 0x31, 0x33, 0x3a, 0x33, 0x62,
		0x3a, 0x32, 0x32, 0x3a, 0x61, 0x64, 0x3a, 0x30, 0x36, 0x3a, 0x39, 0x35, 0x3a, 0x37, 0x37, 0x3a, 0x33,
		0x33, 0x3a, 0x62, 0x66, 0x3a, 0x62, 0x61, 0x3a, 0x39, 0x30, 0x3a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
		0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x39, 0x64,
		0x3a, 0x35, 0x32, 0x3a, 0x39, 0x61, 0x3a, 0x61, 0x31, 0x3a, 0x34, 0x36, 0x3a, 0x35, 0x35, 0x3a, 0x32,
		0x31, 0x3a, 0x30, 0x61, 0x3a, 0x32, 0x64, 0x3a, 0x64, 0x38, 0x3a, 0x38, 0x62, 0x3a, 0x30, 0x32, 0x3a,
		0x66, 0x33, 0x3a, 0x33, 0x63, 0x3a, 0x34, 0x35, 0x3a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
		0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x34, 0x35, 0x3a, 0x33,
		0x61, 0x3a, 0x33, 0x66, 0x3a, 0x30, 0x36, 0x3a, 0x38, 0x66, 0x3a, 0x62, 0x65, 0x3a, 0x37, 0x39, 0x3a,
		0x31, 0x38, 0x3a, 0x35, 0x33, 0x3a, 0x37, 0x38, 0x3a, 0x32, 0x65, 0x3a, 0x62, 0x37, 0x3a, 0x66, 0x66,
		0x3a, 0x36, 0x32, 0x3a, 0x30, 0x63, 0x3a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
		0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x34, 0x65, 0x3a, 0x65, 0x63, 0x3a,
		0x62, 0x32, 0x3a, 0x30, 0x63, 0x3a, 0x33, 0x61, 0x3a, 0x66, 0x30, 0x3a, 0x61, 0x30, 0x3a, 0x34, 0x34,
		0x3a, 0x61, 0x30, 0x3a, 0x62, 0x31, 0x3a, 0x65, 0x35, 0x3a, 0x31, 0x30, 0x3a, 0x66, 0x64, 0x3a, 0x37,
		0x36, 0x3a, 0x30, 0x31, 0x3a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
		0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x37, 0x38, 0x3a, 0x39, 0x39, 0x3a, 0x65, 0x35,
		0x3a, 0x62, 0x61, 0x3a, 0x66, 0x66, 0x3a, 0x63, 0x34, 0x3a, 0x39, 0x33, 0x3a, 0x61, 0x61, 0x3a, 0x38,
		0x30, 0x3a, 0x35, 0x32, 0x3a, 0x39, 0x62, 0x3a, 0x36, 0x36, 0x3a, 0x31, 0x62, 0x3a, 0x65, 0x35, 0x3a,
		0x31, 0x33, 0x3a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
		0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x66, 0x64, 0x3a, 0x35, 0x61, 0x3a, 0x66, 0x64, 0x3a, 0x35,
		0x66, 0x3a, 0x61, 0x30, 0x3a, 0x38, 0x37, 0x3a, 0x38, 0x38, 0x3a, 0x66, 0x66, 0x3a, 0x39, 0x64, 0x3a,
		0x30, 0x35, 0x3a, 0x32, 0x39, 0x3a, 0x33, 0x39, 0x3a, 0x34, 0x64, 0x3a, 0x31, 0x37, 0x3a, 0x32, 0x64,
		0x3a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
		0x20, 0x20, 0x20, 0x20, 0x20, 0x36, 0x38, 0x3a, 0x36, 0x31, 0x3a, 0x39, 0x64, 0x3a, 0x32, 0x65, 0x3a,
		0x39, 0x33, 0x3a, 0x38, 0x64, 0x3a, 0x31, 0x35, 0x3a, 0x34, 0x30, 0x3a, 0x61, 0x62, 0x3a, 0x66, 0x35,
		0x3a, 0x33, 0x35, 0x3a, 0x61, 0x33, 0x3a, 0x38, 0x36, 0x3a, 0x32, 0x64, 0x3a, 0x62, 0x31, 0x3a, 0x0a,
		0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
		0x20, 0x20, 0x20, 0x65, 0x31, 0x3a, 0x64, 0x37, 0x3a, 0x61, 0x64, 0x3a, 0x65, 0x33, 0x3a, 0x33, 0x30,
		0x3a, 0x63, 0x31, 0x3a, 0x36, 0x33, 0x3a, 0x38, 0x66, 0x3a, 0x33, 0x36, 0x3a, 0x33, 0x37, 0x3a, 0x30,
		0x36, 0x3a, 0x66, 0x63, 0x3a, 0x30, 0x36, 0x3a, 0x36, 0x38, 0x3a, 0x31, 0x66, 0x3a, 0x0a, 0x20, 0x20,
		0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
		0x20, 0x63, 0x31, 0x3a, 0x65, 0x62, 0x3a, 0x31, 0x38, 0x3a, 0x37, 0x37, 0x3a, 0x61, 0x37, 0x3a, 0x39,
		0x32, 0x3a, 0x62, 0x61, 0x3a, 0x32, 0x62, 0x3a, 0x37, 0x32, 0x3a, 0x32, 0x65, 0x3a, 0x66, 0x30, 0x3a,
		0x31, 0x35, 0x3a, 0x31, 0x32, 0x3a, 0x38, 0x33, 0x3a, 0x32, 0x32, 0x3a, 0x0a, 0x20, 0x20, 0x20, 0x20,
		0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x37,
		0x33, 0x3a, 0x63, 0x66, 0x3a, 0x63, 0x37, 0x3a, 0x64, 0x34, 0x3a, 0x39, 0x39, 0x3a, 0x34, 0x32, 0x3a,
		0x30, 0x30, 0x3a, 0x61, 0x38, 0x3a, 0x32, 0x39, 0x3a, 0x31, 0x63, 0x3a, 0x32, 0x38, 0x3a, 0x64, 0x35,
		0x3a, 0x63, 0x30, 0x3a, 0x63, 0x61, 0x3a, 0x35, 0x32, 0x3a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
		0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x34, 0x30, 0x3a,
		0x62, 0x62, 0x3a, 0x64, 0x38, 0x3a, 0x30, 0x35, 0x3a, 0x66, 0x31, 0x3a, 0x61, 0x65, 0x3a, 0x62, 0x32,
		0x3a, 0x35, 0x32, 0x3a, 0x30, 0x33, 0x3a, 0x39, 0x36, 0x3a, 0x38, 0x63, 0x3a, 0x66, 0x35, 0x3a, 0x37,
		0x37, 0x3a, 0x63, 0x30, 0x3a, 0x62, 0x34, 0x3a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
		0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x38, 0x39, 0x3a, 0x62, 0x36,
		0x3a, 0x34, 0x31, 0x3a, 0x63, 0x37, 0x3a, 0x34, 0x32, 0x3a, 0x62, 0x39, 0x3a, 0x32, 0x64, 0x3a, 0x63,
		0x66, 0x3a, 0x62, 0x66, 0x3a, 0x65, 0x39, 0x3a, 0x36, 0x31, 0x3a, 0x31, 0x31, 0x3a, 0x66, 0x39, 0x3a,
		0x35, 0x30, 0x3a, 0x64, 0x66, 0x3a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
		0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x66, 0x3a, 0x39, 0x36, 0x3a, 0x63,
		0x61, 0x3a, 0x38, 0x63, 0x3a, 0x36, 0x31, 0x3a, 0x66, 0x31, 0x3a, 0x31, 0x30, 0x3a, 0x30, 0x66, 0x3a,
		0x36, 0x62, 0x3a, 0x33, 0x62, 0x3a, 0x33, 0x33, 0x3a, 0x66, 0x61, 0x3a, 0x64, 0x32, 0x3a, 0x32, 0x65,
		0x3a, 0x34, 0x31, 0x3a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
		0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x63, 0x31, 0x3a, 0x30, 0x30, 0x3a, 0x35, 0x61, 0x3a,
		0x31, 0x61, 0x3a, 0x64, 0x32, 0x3a, 0x65, 0x35, 0x3a, 0x61, 0x39, 0x3a, 0x65, 0x36, 0x3a, 0x33, 0x65,
		0x3a, 0x61, 0x37, 0x3a, 0x30, 0x33, 0x3a, 0x34, 0x63, 0x3a, 0x39, 0x62, 0x3a, 0x34, 0x37, 0x3a, 0x30,
		0x35, 0x3a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
		0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, 0x32, 0x3a, 0x33, 0x65, 0x3a, 0x37, 0x34, 0x3a, 0x30, 0x39,
		0x3a, 0x35, 0x63, 0x3a, 0x64, 0x30, 0x3a, 0x32, 0x35, 0x3a, 0x35, 0x33, 0x3a, 0x35, 0x65, 0x3a, 0x37,
		0x31, 0x3a, 0x34, 0x39, 0x3a, 0x65, 0x62, 0x3a, 0x39, 0x31, 0x3a, 0x34, 0x66, 0x3a, 0x30, 0x30, 0x3a,
		0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
		0x20, 0x20, 0x20, 0x20, 0x36, 0x33, 0x3a, 0x64, 0x33, 0x3a, 0x66, 0x64, 0x3a, 0x62, 0x62, 0x3a, 0x38,
		0x65, 0x3a, 0x35, 0x30, 0x3a, 0x39, 0x61, 0x3a, 0x33, 0x37, 0x3a, 0x62, 0x33, 0x3a, 0x30, 0x32, 0x3a,
		0x66, 0x66, 0x3a, 0x36, 0x36, 0x3a, 0x37, 0x35, 0x3a, 0x36, 0x62, 0x3a, 0x37, 0x32, 0x3a, 0x0a, 0x20,
		0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
		0x20, 0x20, 0x39, 0x65, 0x3a, 0x31, 0x31, 0x3a, 0x66, 0x64, 0x3a, 0x35, 0x62, 0x3a, 0x39, 0x64, 0x3a,
		0x61, 0x64, 0x3a, 0x30, 0x61, 0x3a, 0x30, 0x31, 0x3a, 0x37, 0x32, 0x3a, 0x36, 0x61, 0x3a, 0x65, 0x63,
		0x3a, 0x38, 0x63, 0x3a, 0x32, 0x35, 0x3a, 0x34, 0x31, 0x3a, 0x30, 0x37, 0x3a, 0x0a, 0x20, 0x20, 0x20,
		0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
		0x64, 0x30, 0x3a, 0x62, 0x66, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
		0x20, 0x20, 0x20, 0x20, 0x20, 0x45, 0x78, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x3a, 0x20, 0x36, 0x35,
		0x35, 0x33, 0x37, 0x20, 0x28, 0x30, 0x78, 0x31, 0x30, 0x30, 0x30, 0x31, 0x29, 0x0a, 0x20, 0x20, 0x20,
		0x20, 0x20, 0x20, 0x20, 0x20, 0x58, 0x35, 0x30, 0x39, 0x76, 0x33, 0x20, 0x65, 0x78, 0x74, 0x65, 0x6e,
		0x73, 0x69, 0x6f, 0x6e, 0x73, 0x3a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
		0x20, 0x20, 0x58, 0x35, 0x30, 0x39, 0x76, 0x33, 0x20, 0x42, 0x61, 0x73, 0x69, 0x63, 0x20, 0x43, 0x6f,
		0x6e, 0x73, 0x74, 0x72, 0x61, 0x69, 0x6e, 0x74, 0x73, 0x3a, 0x20, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
		0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x43, 0x41, 0x3a, 0x46, 0x41, 0x4c,
		0x53, 0x45, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4e, 0x65,
		0x74, 0x73, 0x63, 0x61, 0x70, 0x65, 0x20, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x3a, 0x20, 0x0a,
		0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4f,
		0x70, 0x65, 0x6e, 0x53, 0x53, 0x4c, 0x20, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x20,
		0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
		0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x58, 0x35, 0x30, 0x39, 0x76, 0x33, 0x20, 0x53, 0x75, 0x62,
		0x6a, 0x65, 0x63, 0x74, 0x20, 0x4b, 0x65, 0x79, 0x20, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69,
		0x65, 0x72, 0x3a, 0x20, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
		0x20, 0x20, 0x20, 0x20, 0x42, 0x36, 0x3a, 0x41, 0x30, 0x3a, 0x34, 0x38, 0x3a, 0x34, 0x46, 0x3a, 0x33,
		0x42, 0x3a, 0x43, 0x33, 0x3a, 0x42, 0x46, 0x3a, 0x45, 0x31, 0x3a, 0x31, 0x38, 0x3a, 0x37, 0x42, 0x3a,
		0x46, 0x30, 0x3a, 0x33, 0x36, 0x3a, 0x39, 0x42, 0x3a, 0x30, 0x37, 0x3a, 0x37, 0x31, 0x3a, 0x38, 0x31,
		0x3a, 0x44, 0x30, 0x3a, 0x36, 0x46, 0x3a, 0x43, 0x44, 0x3a, 0x44, 0x33, 0x0a, 0x20, 0x20, 0x20, 0x20,
		0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x58, 0x35, 0x30, 0x39, 0x76, 0x33, 0x20, 0x41, 0x75,
		0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x20, 0x4b, 0x65, 0x79, 0x20, 0x49, 0x64, 0x65, 0x6e, 0x74,
		0x69, 0x66, 0x69, 0x65, 0x72, 0x3a, 0x20, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
		0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6b, 0x65, 0x79, 0x69, 0x64, 0x3a, 0x44, 0x33, 0x3a, 0x35,
		0x34, 0x3a, 0x38, 0x41, 0x3a, 0x34, 0x42, 0x3a, 0x43, 0x32, 0x3a, 0x36, 0x34, 0x3a, 0x39, 0x34, 0x3a,
		0x42, 0x46, 0x3a, 0x39, 0x45, 0x3a, 0x46, 0x39, 0x3a, 0x34, 0x41, 0x3a, 0x38, 0x38, 0x3a, 0x43, 0x37,
		0x3a, 0x45, 0x39, 0x3a, 0x45, 0x32, 0x3a, 0x31, 0x30, 0x3a, 0x31, 0x30, 0x3a, 0x30, 0x37, 0x3a, 0x43,
		0x45, 0x3a, 0x39, 0x46, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75,
		0x72, 0x65, 0x20, 0x41, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x3a, 0x20, 0x73, 0x68, 0x61,
		0x32, 0x35, 0x36, 0x57, 0x69, 0x74, 0x68, 0x52, 0x53, 0x41, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74,
		0x69, 0x6f, 0x6e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x63, 0x3a, 0x65,
		0x38, 0x3a, 0x38, 0x36, 0x3a, 0x32, 0x34, 0x3a, 0x66, 0x38, 0x3a, 0x35, 0x33, 0x3a, 0x36, 0x35, 0x3a,
		0x63, 0x61, 0x3a, 0x38, 0x61, 0x3a, 0x38, 0x35, 0x3a, 0x61, 0x36, 0x3a, 0x32, 0x62, 0x3a, 0x31, 0x39,
		0x3a, 0x39, 0x64, 0x3a, 0x64, 0x31, 0x3a, 0x62, 0x34, 0x3a, 0x62, 0x63, 0x3a, 0x62, 0x32, 0x3a, 0x0a,
		0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x65, 0x37, 0x3a, 0x30, 0x32, 0x3a, 0x33, 0x37,
		0x3a, 0x34, 0x37, 0x3a, 0x39, 0x61, 0x3a, 0x30, 0x35, 0x3a, 0x36, 0x32, 0x3a, 0x38, 0x31, 0x3a, 0x32,
		0x63, 0x3a, 0x63, 0x31, 0x3a, 0x66, 0x61, 0x3a, 0x38, 0x62, 0x3a, 0x30, 0x38, 0x3a, 0x30, 0x31, 0x3a,
		0x39, 0x35, 0x3a, 0x38, 0x38, 0x3a, 0x33, 0x31, 0x3a, 0x39, 0x63, 0x3a, 0x0a, 0x20, 0x20, 0x20, 0x20,
		0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x35, 0x3a, 0x63, 0x65, 0x3a, 0x35, 0x32, 0x3a, 0x32, 0x37, 0x3a,
		0x66, 0x34, 0x3a, 0x34, 0x66, 0x3a, 0x61, 0x37, 0x3a, 0x32, 0x61, 0x3a, 0x39, 0x39, 0x3a, 0x63, 0x30,
		0x3a, 0x39, 0x65, 0x3a, 0x61, 0x62, 0x3a, 0x36, 0x32, 0x3a, 0x62, 0x33, 0x3a, 0x61, 0x38, 0x3a, 0x63,
		0x62, 0x3a, 0x34, 0x31, 0x3a, 0x34, 0x64, 0x3a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
		0x20, 0x39, 0x64, 0x3a, 0x30, 0x33, 0x3a, 0x38, 0x33, 0x3a, 0x64, 0x63, 0x3a, 0x38, 0x39, 0x3a, 0x38,
		0x64, 0x3a, 0x35, 0x36, 0x3a, 0x36, 0x65, 0x3a, 0x39, 0x63, 0x3a, 0x63, 0x30, 0x3a, 0x35, 0x37, 0x3a,
		0x33, 0x39, 0x3a, 0x35, 0x31, 0x3a, 0x63, 0x36, 0x3a, 0x66, 0x37, 0x3a, 0x34, 0x63, 0x3a, 0x34, 0x36,
		0x3a, 0x33, 0x30, 0x3a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x63, 0x64, 0x3a,
		0x31, 0x65, 0x3a, 0x37, 0x38, 0x3a, 0x30, 0x61, 0x3a, 0x39, 0x66, 0x3a, 0x64, 0x33, 0x3a, 0x64, 0x35,
		0x3a, 0x32, 0x65, 0x3a, 0x37, 0x64, 0x3a, 0x66, 0x34, 0x3a, 0x35, 0x65, 0x3a, 0x36, 0x32, 0x3a, 0x38,
		0x30, 0x3a, 0x32, 0x38, 0x3a, 0x66, 0x32, 0x3a, 0x39, 0x65, 0x3a, 0x34, 0x34, 0x3a, 0x62, 0x34, 0x3a,
		0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x63, 0x3a, 0x63, 0x61, 0x3a, 0x33,
		0x62, 0x3a, 0x33, 0x33, 0x3a, 0x65, 0x34, 0x3a, 0x38, 0x37, 0x3a, 0x61, 0x37, 0x3a, 0x36, 0x30, 0x3a,
		0x34, 0x32, 0x3a, 0x37, 0x34, 0x3a, 0x65, 0x36, 0x3a, 0x37, 0x35, 0x3a, 0x39, 0x66, 0x3a, 0x62, 0x66,
		0x3a, 0x34, 0x31, 0x3a, 0x36, 0x66, 0x3a, 0x66, 0x36, 0x3a, 0x33, 0x61, 0x3a, 0x0a, 0x20, 0x20, 0x20,
		0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x34, 0x3a, 0x65, 0x33, 0x3a, 0x34, 0x39, 0x3a, 0x61, 0x61,
		0x3a, 0x36, 0x35, 0x3a, 0x62, 0x39, 0x3a, 0x33, 0x61, 0x3a, 0x61, 0x31, 0x3a, 0x36, 0x38, 0x3a, 0x32,
		0x62, 0x3a, 0x63, 0x37, 0x3a, 0x33, 0x39, 0x3a, 0x38, 0x34, 0x3a, 0x64, 0x62, 0x3a, 0x63, 0x36, 0x3a,
		0x35, 0x36, 0x3a, 0x61, 0x31, 0x3a, 0x31, 0x34, 0x3a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
		0x20, 0x20, 0x64, 0x37, 0x3a, 0x65, 0x65, 0x3a, 0x38, 0x36, 0x3a, 0x34, 0x66, 0x3a, 0x38, 0x65, 0x3a,
		0x37, 0x39, 0x3a, 0x36, 0x39, 0x3a, 0x61, 0x34, 0x3a, 0x66, 0x32, 0x3a, 0x65, 0x61, 0x3a, 0x64, 0x36,
		0x3a, 0x63, 0x61, 0x3a, 0x66, 0x37, 0x3a, 0x66, 0x66, 0x3a, 0x66, 0x35, 0x3a, 0x32, 0x30, 0x3a, 0x63,
		0x63, 0x3a, 0x34, 0x61, 0x3a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x33, 0x39,
		0x3a, 0x34, 0x37, 0x3a, 0x64, 0x66, 0x3a, 0x31, 0x61, 0x3a, 0x62, 0x39, 0x3a, 0x37, 0x36, 0x3a, 0x35,
		0x65, 0x3a, 0x31, 0x62, 0x3a, 0x35, 0x61, 0x3a, 0x30, 0x66, 0x3a, 0x32, 0x61, 0x3a, 0x37, 0x35, 0x3a,
		0x37, 0x64, 0x3a, 0x38, 0x66, 0x3a, 0x37, 0x32, 0x3a, 0x32, 0x63, 0x3a, 0x30, 0x61, 0x3a, 0x63, 0x62,
		0x3a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x62, 0x3a, 0x66, 0x37, 0x3a,
		0x66, 0x36, 0x3a, 0x61, 0x63, 0x3a, 0x33, 0x39, 0x3a, 0x33, 0x32, 0x3a, 0x66, 0x62, 0x3a, 0x63, 0x32,
		0x3a, 0x33, 0x33, 0x3a, 0x65, 0x66, 0x3a, 0x33, 0x37, 0x3a, 0x32, 0x35, 0x3a, 0x37, 0x65, 0x3a, 0x37,
		0x30, 0x3a, 0x34, 0x39, 0x3a, 0x64, 0x33, 0x3a, 0x63, 0x61, 0x3a, 0x38, 0x38, 0x3a, 0x0a, 0x20, 0x20,
		0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x39, 0x65, 0x3a, 0x35, 0x39, 0x3a, 0x33, 0x31, 0x3a, 0x36,
		0x36, 0x3a, 0x66, 0x37, 0x3a, 0x64, 0x31, 0x3a, 0x32, 0x38, 0x3a, 0x38, 0x37, 0x3a, 0x31, 0x30, 0x3a,
		0x35, 0x34, 0x3a, 0x37, 0x31, 0x3a, 0x35, 0x64, 0x3a, 0x65, 0x62, 0x3a, 0x36, 0x63, 0x3a, 0x66, 0x33,
		0x3a, 0x35, 0x37, 0x3a, 0x37, 0x37, 0x3a, 0x35, 0x35, 0x3a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
		0x20, 0x20, 0x20, 0x65, 0x35, 0x3a, 0x62, 0x61, 0x3a, 0x30, 0x61, 0x3a, 0x66, 0x36, 0x3a, 0x38, 0x36,
		0x3a, 0x31, 0x62, 0x3a, 0x35, 0x35, 0x3a, 0x37, 0x63, 0x3a, 0x35, 0x64, 0x3a, 0x36, 0x61, 0x3a, 0x63,
		0x33, 0x3a, 0x61, 0x32, 0x3a, 0x65, 0x37, 0x3a, 0x65, 0x31, 0x3a, 0x62, 0x38, 0x3a, 0x33, 0x39, 0x3a,
		0x66, 0x62, 0x3a, 0x34, 0x31, 0x3a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x36,
		0x34, 0x3a, 0x33, 0x35, 0x3a, 0x61, 0x31, 0x3a, 0x34, 0x31, 0x3a, 0x30, 0x33, 0x3a, 0x64, 0x38, 0x3a,
		0x38, 0x37, 0x3a, 0x66, 0x39, 0x3a, 0x65, 0x62, 0x3a, 0x64, 0x34, 0x3a, 0x64, 0x36, 0x3a, 0x36, 0x65,
		0x3a, 0x65, 0x39, 0x3a, 0x37, 0x34, 0x3a, 0x36, 0x64, 0x3a, 0x30, 0x62, 0x3a, 0x66, 0x64, 0x3a, 0x37,
		0x31, 0x3a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x37, 0x36, 0x3a, 0x30, 0x37,
		0x3a, 0x33, 0x34, 0x3a, 0x39, 0x66, 0x3a, 0x39, 0x37, 0x3a, 0x66, 0x62, 0x3a, 0x39, 0x61, 0x3a, 0x39,
		0x65, 0x3a, 0x39, 0x62, 0x3a, 0x62, 0x32, 0x3a, 0x39, 0x38, 0x3a, 0x39, 0x65, 0x3a, 0x37, 0x35, 0x3a,
		0x61, 0x65, 0x3a, 0x32, 0x63, 0x3a, 0x36, 0x63, 0x3a, 0x64, 0x61, 0x3a, 0x33, 0x39, 0x3a, 0x0a, 0x20,
		0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x38, 0x64, 0x3a, 0x37, 0x39, 0x3a, 0x38, 0x39, 0x3a,
		0x35, 0x37, 0x0a, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x20, 0x43, 0x45, 0x52,
		0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x0a, 0x4d, 0x49, 0x49,
		0x44, 0x6d, 0x54, 0x43, 0x43, 0x41, 0x6f, 0x47, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x42,
		0x41, 0x54, 0x41, 0x4e, 0x42, 0x67, 0x6b, 0x71, 0x68, 0x6b, 0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41,
		0x51, 0x73, 0x46, 0x41, 0x44, 0x42, 0x52, 0x4d, 0x51, 0x73, 0x77, 0x43, 0x51, 0x59, 0x44, 0x56, 0x51,
		0x51, 0x47, 0x45, 0x77, 0x4a, 0x44, 0x54, 0x6a, 0x45, 0x52, 0x0a, 0x4d, 0x41, 0x38, 0x47, 0x41, 0x31,
		0x55, 0x45, 0x43, 0x41, 0x77, 0x49, 0x55, 0x32, 0x68, 0x68, 0x62, 0x6d, 0x64, 0x6f, 0x59, 0x57, 0x6b,
		0x78, 0x45, 0x54, 0x41, 0x50, 0x42, 0x67, 0x4e, 0x56, 0x42, 0x41, 0x63, 0x4d, 0x43, 0x46, 0x4e, 0x6f,
		0x59, 0x57, 0x35, 0x6e, 0x61, 0x47, 0x46, 0x70, 0x4d, 0x51, 0x38, 0x77, 0x44, 0x51, 0x59, 0x44, 0x56,
		0x51, 0x51, 0x4b, 0x44, 0x41, 0x5a, 0x49, 0x0a, 0x64, 0x57, 0x46, 0x33, 0x5a, 0x57, 0x6b, 0x78, 0x43,
		0x7a, 0x41, 0x4a, 0x42, 0x67, 0x4e, 0x56, 0x42, 0x41, 0x4d, 0x4d, 0x41, 0x6d, 0x4e, 0x68, 0x4d, 0x42,
		0x34, 0x58, 0x44, 0x54, 0x49, 0x79, 0x4d, 0x54, 0x45, 0x79, 0x4e, 0x54, 0x41, 0x7a, 0x4e, 0x44, 0x55,
		0x30, 0x4f, 0x46, 0x6f, 0x58, 0x44, 0x54, 0x49, 0x7a, 0x4d, 0x54, 0x45, 0x78, 0x4e, 0x6a, 0x41, 0x7a,
		0x4e, 0x44, 0x55, 0x30, 0x0a, 0x4f, 0x46, 0x6f, 0x77, 0x55, 0x6a, 0x45, 0x4c, 0x4d, 0x41, 0x6b, 0x47,
		0x41, 0x31, 0x55, 0x45, 0x42, 0x68, 0x4d, 0x43, 0x51, 0x30, 0x34, 0x78, 0x45, 0x54, 0x41, 0x50, 0x42,
		0x67, 0x4e, 0x56, 0x42, 0x41, 0x67, 0x4d, 0x43, 0x46, 0x4e, 0x6f, 0x59, 0x57, 0x35, 0x6e, 0x61, 0x47,
		0x46, 0x70, 0x4d, 0x52, 0x45, 0x77, 0x44, 0x77, 0x59, 0x44, 0x56, 0x51, 0x51, 0x48, 0x44, 0x41, 0x68,
		0x54, 0x0a, 0x61, 0x47, 0x46, 0x75, 0x5a, 0x32, 0x68, 0x68, 0x61, 0x54, 0x45, 0x50, 0x4d, 0x41, 0x30,
		0x47, 0x41, 0x31, 0x55, 0x45, 0x43, 0x67, 0x77, 0x47, 0x53, 0x48, 0x56, 0x68, 0x64, 0x32, 0x56, 0x70,
		0x4d, 0x51, 0x77, 0x77, 0x43, 0x67, 0x59, 0x44, 0x56, 0x51, 0x51, 0x44, 0x44, 0x41, 0x4e, 0x72, 0x64,
		0x47, 0x45, 0x77, 0x67, 0x67, 0x45, 0x69, 0x4d, 0x41, 0x30, 0x47, 0x43, 0x53, 0x71, 0x47, 0x0a, 0x53,
		0x49, 0x62, 0x33, 0x44, 0x51, 0x45, 0x42, 0x41, 0x51, 0x55, 0x41, 0x41, 0x34, 0x49, 0x42, 0x44, 0x77,
		0x41, 0x77, 0x67, 0x67, 0x45, 0x4b, 0x41, 0x6f, 0x49, 0x42, 0x41, 0x51, 0x44, 0x51, 0x57, 0x4b, 0x6b,
		0x54, 0x4f, 0x79, 0x4b, 0x74, 0x42, 0x70, 0x56, 0x33, 0x4d, 0x37, 0x2b, 0x36, 0x6b, 0x4a, 0x31, 0x53,
		0x6d, 0x71, 0x46, 0x47, 0x56, 0x53, 0x45, 0x4b, 0x4c, 0x64, 0x69, 0x4c, 0x0a, 0x41, 0x76, 0x4d, 0x38,
		0x52, 0x55, 0x55, 0x36, 0x50, 0x77, 0x61, 0x50, 0x76, 0x6e, 0x6b, 0x59, 0x55, 0x33, 0x67, 0x75, 0x74,
		0x2f, 0x39, 0x69, 0x44, 0x45, 0x37, 0x73, 0x73, 0x67, 0x77, 0x36, 0x38, 0x4b, 0x42, 0x45, 0x6f, 0x4c,
		0x48, 0x6c, 0x45, 0x50, 0x31, 0x32, 0x41, 0x58, 0x69, 0x5a, 0x35, 0x62, 0x72, 0x2f, 0x78, 0x4a, 0x4f,
		0x71, 0x67, 0x46, 0x4b, 0x62, 0x5a, 0x68, 0x76, 0x6c, 0x0a, 0x45, 0x2f, 0x31, 0x61, 0x2f, 0x56, 0x2b,
		0x67, 0x68, 0x34, 0x6a, 0x2f, 0x6e, 0x51, 0x55, 0x70, 0x4f, 0x55, 0x30, 0x58, 0x4c, 0x57, 0x68, 0x68,
		0x6e, 0x53, 0x36, 0x54, 0x6a, 0x52, 0x56, 0x41, 0x71, 0x2f, 0x55, 0x31, 0x6f, 0x34, 0x59, 0x74, 0x73,
		0x65, 0x48, 0x58, 0x72, 0x65, 0x4d, 0x77, 0x77, 0x57, 0x4f, 0x50, 0x4e, 0x6a, 0x63, 0x47, 0x2f, 0x41,
		0x5a, 0x6f, 0x48, 0x38, 0x48, 0x72, 0x0a, 0x47, 0x48, 0x65, 0x6e, 0x6b, 0x72, 0x6f, 0x72, 0x63, 0x69,
		0x37, 0x77, 0x46, 0x52, 0x4b, 0x44, 0x49, 0x6e, 0x50, 0x50, 0x78, 0x39, 0x53, 0x5a, 0x51, 0x67, 0x43,
		0x6f, 0x4b, 0x52, 0x77, 0x6f, 0x31, 0x63, 0x44, 0x4b, 0x55, 0x6b, 0x43, 0x37, 0x32, 0x41, 0x58, 0x78,
		0x72, 0x72, 0x4a, 0x53, 0x41, 0x35, 0x61, 0x4d, 0x39, 0x58, 0x66, 0x41, 0x74, 0x49, 0x6d, 0x32, 0x51,
		0x63, 0x64, 0x43, 0x0a, 0x75, 0x53, 0x33, 0x50, 0x76, 0x2b, 0x6c, 0x68, 0x45, 0x66, 0x6c, 0x51, 0x33,
		0x37, 0x2b, 0x57, 0x79, 0x6f, 0x78, 0x68, 0x38, 0x52, 0x41, 0x50, 0x61, 0x7a, 0x73, 0x7a, 0x2b, 0x74,
		0x49, 0x75, 0x51, 0x63, 0x45, 0x41, 0x57, 0x68, 0x72, 0x53, 0x35, 0x61, 0x6e, 0x6d, 0x50, 0x71, 0x63,
		0x44, 0x54, 0x4a, 0x74, 0x48, 0x42, 0x52, 0x49, 0x2b, 0x64, 0x41, 0x6c, 0x63, 0x30, 0x43, 0x56, 0x54,
		0x0a, 0x58, 0x6e, 0x46, 0x4a, 0x36, 0x35, 0x46, 0x50, 0x41, 0x47, 0x50, 0x54, 0x2f, 0x62, 0x75, 0x4f,
		0x55, 0x4a, 0x6f, 0x33, 0x73, 0x77, 0x4c, 0x2f, 0x5a, 0x6e, 0x56, 0x72, 0x63, 0x70, 0x34, 0x52, 0x2f,
		0x56, 0x75, 0x64, 0x72, 0x51, 0x6f, 0x42, 0x63, 0x6d, 0x72, 0x73, 0x6a, 0x43, 0x56, 0x42, 0x42, 0x39,
		0x43, 0x2f, 0x41, 0x67, 0x4d, 0x42, 0x41, 0x41, 0x47, 0x6a, 0x65, 0x7a, 0x42, 0x35, 0x0a, 0x4d, 0x41,
		0x6b, 0x47, 0x41, 0x31, 0x55, 0x64, 0x45, 0x77, 0x51, 0x43, 0x4d, 0x41, 0x41, 0x77, 0x4c, 0x41, 0x59,
		0x4a, 0x59, 0x49, 0x5a, 0x49, 0x41, 0x59, 0x62, 0x34, 0x51, 0x67, 0x45, 0x4e, 0x42, 0x42, 0x38, 0x57,
		0x48, 0x55, 0x39, 0x77, 0x5a, 0x57, 0x35, 0x54, 0x55, 0x30, 0x77, 0x67, 0x52, 0x32, 0x56, 0x75, 0x5a,
		0x58, 0x4a, 0x68, 0x64, 0x47, 0x56, 0x6b, 0x49, 0x45, 0x4e, 0x6c, 0x0a, 0x63, 0x6e, 0x52, 0x70, 0x5a,
		0x6d, 0x6c, 0x6a, 0x59, 0x58, 0x52, 0x6c, 0x4d, 0x42, 0x30, 0x47, 0x41, 0x31, 0x55, 0x64, 0x44, 0x67,
		0x51, 0x57, 0x42, 0x42, 0x53, 0x32, 0x6f, 0x45, 0x68, 0x50, 0x4f, 0x38, 0x4f, 0x2f, 0x34, 0x52, 0x68,
		0x37, 0x38, 0x44, 0x61, 0x62, 0x42, 0x33, 0x47, 0x42, 0x30, 0x47, 0x2f, 0x4e, 0x30, 0x7a, 0x41, 0x66,
		0x42, 0x67, 0x4e, 0x56, 0x48, 0x53, 0x4d, 0x45, 0x0a, 0x47, 0x44, 0x41, 0x57, 0x67, 0x42, 0x54, 0x54,
		0x56, 0x49, 0x70, 0x4c, 0x77, 0x6d, 0x53, 0x55, 0x76, 0x35, 0x37, 0x35, 0x53, 0x6f, 0x6a, 0x48, 0x36,
		0x65, 0x49, 0x51, 0x45, 0x41, 0x66, 0x4f, 0x6e, 0x7a, 0x41, 0x4e, 0x42, 0x67, 0x6b, 0x71, 0x68, 0x6b,
		0x69, 0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x73, 0x46, 0x41, 0x41, 0x4f, 0x43, 0x41, 0x51, 0x45,
		0x41, 0x44, 0x4f, 0x69, 0x47, 0x0a, 0x4a, 0x50, 0x68, 0x54, 0x5a, 0x63, 0x71, 0x4b, 0x68, 0x61, 0x59,
		0x72, 0x47, 0x5a, 0x33, 0x52, 0x74, 0x4c, 0x79, 0x79, 0x35, 0x77, 0x49, 0x33, 0x52, 0x35, 0x6f, 0x46,
		0x59, 0x6f, 0x45, 0x73, 0x77, 0x66, 0x71, 0x4c, 0x43, 0x41, 0x47, 0x56, 0x69, 0x44, 0x47, 0x63, 0x42,
		0x63, 0x35, 0x53, 0x4a, 0x2f, 0x52, 0x50, 0x70, 0x79, 0x71, 0x5a, 0x77, 0x4a, 0x36, 0x72, 0x59, 0x72,
		0x4f, 0x6f, 0x0a, 0x79, 0x30, 0x46, 0x4e, 0x6e, 0x51, 0x4f, 0x44, 0x33, 0x49, 0x6d, 0x4e, 0x56, 0x6d,
		0x36, 0x63, 0x77, 0x46, 0x63, 0x35, 0x55, 0x63, 0x62, 0x33, 0x54, 0x45, 0x59, 0x77, 0x7a, 0x52, 0x35,
		0x34, 0x43, 0x70, 0x2f, 0x54, 0x31, 0x53, 0x35, 0x39, 0x39, 0x46, 0x35, 0x69, 0x67, 0x43, 0x6a, 0x79,
		0x6e, 0x6b, 0x53, 0x30, 0x76, 0x4d, 0x6f, 0x37, 0x4d, 0x2b, 0x53, 0x48, 0x70, 0x32, 0x42, 0x43, 0x0a,
		0x64, 0x4f, 0x5a, 0x31, 0x6e, 0x37, 0x39, 0x42, 0x62, 0x2f, 0x59, 0x36, 0x74, 0x4f, 0x4e, 0x4a, 0x71,
		0x6d, 0x57, 0x35, 0x4f, 0x71, 0x46, 0x6f, 0x4b, 0x38, 0x63, 0x35, 0x68, 0x4e, 0x76, 0x47, 0x56, 0x71,
		0x45, 0x55, 0x31, 0x2b, 0x36, 0x47, 0x54, 0x34, 0x35, 0x35, 0x61, 0x61, 0x54, 0x79, 0x36, 0x74, 0x62,
		0x4b, 0x39, 0x2f, 0x2f, 0x31, 0x49, 0x4d, 0x78, 0x4b, 0x4f, 0x55, 0x66, 0x66, 0x0a, 0x47, 0x72, 0x6c,
		0x32, 0x58, 0x68, 0x74, 0x61, 0x44, 0x79, 0x70, 0x31, 0x66, 0x59, 0x39, 0x79, 0x4c, 0x41, 0x72, 0x4c,
		0x43, 0x2f, 0x66, 0x32, 0x72, 0x44, 0x6b, 0x79, 0x2b, 0x38, 0x49, 0x7a, 0x37, 0x7a, 0x63, 0x6c, 0x66,
		0x6e, 0x42, 0x4a, 0x30, 0x38, 0x71, 0x49, 0x6e, 0x6c, 0x6b, 0x78, 0x5a, 0x76, 0x66, 0x52, 0x4b, 0x49,
		0x63, 0x51, 0x56, 0x48, 0x46, 0x64, 0x36, 0x32, 0x7a, 0x7a, 0x0a, 0x56, 0x33, 0x64, 0x56, 0x35, 0x62,
		0x6f, 0x4b, 0x39, 0x6f, 0x59, 0x62, 0x56, 0x58, 0x78, 0x64, 0x61, 0x73, 0x4f, 0x69, 0x35, 0x2b, 0x47,
		0x34, 0x4f, 0x66, 0x74, 0x42, 0x5a, 0x44, 0x57, 0x68, 0x51, 0x51, 0x50, 0x59, 0x68, 0x2f, 0x6e, 0x72,
		0x31, 0x4e, 0x5a, 0x75, 0x36, 0x58, 0x52, 0x74, 0x43, 0x2f, 0x31, 0x78, 0x64, 0x67, 0x63, 0x30, 0x6e,
		0x35, 0x66, 0x37, 0x6d, 0x70, 0x36, 0x62, 0x0a, 0x73, 0x70, 0x69, 0x65, 0x64, 0x61, 0x34, 0x73, 0x62,
		0x4e, 0x6f, 0x35, 0x6a, 0x58, 0x6d, 0x4a, 0x56, 0x77, 0x3d, 0x3d, 0x0a, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d,
		0x45, 0x4e, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2d, 0x2d,
		0x2d, 0x2d, 0x2d, 0x0a}
)

var (
	decKey = []byte{
		0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50,
		0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e}
)

var (
	emptyClientInfoErr  = "create empty ClientInfo error"
	createClientInfoErr = "create test ClientInfo error"
	sendrRportErr       = "test SendReport error"
	testClientInfo      = map[string]string{"test name": "test value"}
)

func CreateServerConfigFile() {
	ioutil.WriteFile(configFilePath, []byte(serverConfig), 0644)
}

func RemoveConfigFile() {
	os.Remove(configFilePath)
}

func prepare() {
	CreateServerConfigFile()
	// config.InitFlags()
	config.LoadConfigs()
	config.HandleFlags()
}

func release() {
	RemoveConfigFile()
	RemoveFiles()
}

func TestClientapi(t *testing.T) {
	print("\nThis is in TestClientapi\n")
	CreateServerConfigFile()
	defer RemoveConfigFile()

	config.InitFlags()
	config.LoadConfigs()
	defer RemoveFiles()
	config.HandleFlags()
	server := config.GetServerPort()

	go StartServer(server)
	defer StopServer()

	ras, err := CreateConn(server)
	if err != nil {
		t.Errorf("fail to Create connection, %v", err)
	}
	defer ReleaseConn(ras)
	ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
	defer cancel()

	EKpubBlock, _ := pem.Decode([]byte(EKpubPEM))
	reqEC := GenerateEKCertRequest{
		EkPub: EKpubBlock.Bytes,
	}
	rspEC, err := ras.c.GenerateEKCert(ctx, &reqEC)
	if err != nil {
		t.Errorf("test GenerateEKCert error %v", err)
	}
	IKpubBlock, _ := pem.Decode([]byte(IKpubPEM))
	_, err = ras.c.GenerateIKCert(ctx, &GenerateIKCertRequest{
		EkCert: rspEC.EkCert,
		IkPub:  IKpubBlock.Bytes,
		IkName: IKName,
	})
	if err != nil {
		t.Errorf("test GenerateIKCert error %v", err)
	}

	// test empty request
	_, err = ras.c.RegisterClient(ctx, &RegisterClientRequest{})
	if err == nil {
		t.Errorf("test RegisterClient with empty request failed")
	}
	template := x509.Certificate{
		SerialNumber: big.NewInt(cryptotools.GetSerialNumber()),
		NotBefore:    time.Now(),
		NotAfter:     time.Now().AddDate(1, 0, 0),
		KeyUsage: x509.KeyUsageDigitalSignature |
			x509.KeyUsageKeyEncipherment | x509.KeyUsageCertSign,
		IsCA:           false,
		MaxPathLenZero: true,
		IPAddresses:    []net.IP{net.ParseIP(config.GetIP())},
	}
	ikCertDer, _ := cryptotools.GenerateCertificate(&template,
		config.GetPcaKeyCert(), IKpubBlock.Bytes, config.GetPcaPrivateKey())

	ci, err := json.Marshal(testClientInfo)
	if err != nil {
		t.Error(createClientInfoErr)
	}
	r2, err := ras.c.RegisterClient(ctx, &RegisterClientRequest{
		Cert:       ikCertDer,
		ClientInfo: string(ci),
	})
	if err != nil {
		t.Errorf("test RegisterClient error %v", err)
	}

	// test empty clientId
	_, err = ras.c.SendHeartbeat(ctx, &SendHeartbeatRequest{})
	if err != nil {
		t.Errorf("test SendHeartbeat with empty ClientId failed")
	}

	HBrep, err := ras.c.SendHeartbeat(ctx, &SendHeartbeatRequest{ClientId: r2.GetClientId()})
	if err != nil {
		t.Errorf("test SendHeartbeat error %v", err)
	}

	// test empty report
	srRep, _ := ras.c.SendReport(ctx, &SendReportRequest{})
	if srRep.GetResult() {
		t.Errorf("test SendReport with empty report failed")
	}

	testbios, err := ioutil.ReadFile(BIOSLogPath)
	if err != nil {
		t.Errorf("ReadFile error %v", err)
	}
	testima, err := ioutil.ReadFile(IMALogPath)
	if err != nil {
		t.Errorf("ReadFile error %v", err)
	}
	srRep, _ = ras.c.SendReport(ctx, &SendReportRequest{
		ClientId:   r2.GetClientId(),
		Nonce:      HBrep.ClientConfig.Nonce,
		ClientInfo: string(ci),
		Quoted:     testquote,
		Signature:  testsignature,
		Manifests: []*Manifest{
			0: {Key: "pcr", Value: testpcr},
			1: {Key: "bios", Value: testbios},
			2: {Key: "ima", Value: testima},
		},
	})
	if !srRep.GetResult() {
		t.Errorf(sendrRportErr)
	}

	// test empty clientId
	_, err = ras.c.UnregisterClient(ctx, &UnregisterClientRequest{})
	if err != nil {
		t.Errorf("test UnregisterClient with empty clientId failed %v", err)
	}

	_, err = ras.c.UnregisterClient(ctx, &UnregisterClientRequest{
		ClientId: r2.GetClientId(),
	})
	if err != nil {
		t.Errorf("test UnregisterClient error %v", err)
	}
	defer trustmgr.DeleteClientByID(r2.GetClientId())
	defer trustmgr.DeleteReportByID(r2.GetClientId())
}

func TestClientapiInitKTA(t *testing.T) {
	print("\nThis is in TestClientapiInitKTA\n")
	prepare()
	defer release()
	server := config.GetServerPort()
	go StartServer(server)
	defer StopServer()

	ras, err := CreateConn(server)
	if err != nil {
		t.Errorf("fail to Create connection %v", err)
	}
	defer ReleaseConn(ras)
	ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
	defer cancel()

	err = kcmstools.SaveCert([]byte(kcmCert), certPath, kcmFileName)
	if err != nil {
		t.Errorf("save KCM Cert failed, error, %v", err)
	}
	// test SendKCMPubKeyCert
	_, err = ras.c.SendKCMPubKeyCert(ctx, &SendKCMPubKeyCertRequest{})
	if err != nil {
		t.Errorf("test SendKCMPubKeyCert failed, %v", err)
	}

	// test empty deviceId
	_, err = ras.c.VerifyKTAPubKeyCert(ctx, &VerifyKTAPubKeyCertRequest{})
	if err != nil {
		t.Errorf("test VerifyKTAPubKeyCert with empty deviceId failed %v", err)
	}

	err = kcmstools.SaveCert(ktacert, certPath, ktaFileName)
	if err != nil {
		t.Errorf(constSaveKTACertFailed, err)
	}
	err = kcmstools.SaveCert(rootcert, certPath, rootFileName)
	if err != nil {
		t.Errorf("save Root Cert failed, error %v", err)
	}
	defer os.RemoveAll(certPath)
	_, err = ras.c.VerifyKTAPubKeyCert(ctx, &VerifyKTAPubKeyCertRequest{
		ClientId:      deviceId,
		KtaPubKeyCert: ktacert,
	})
	if err != nil {
		t.Errorf("test VerifyKTAPubKeyCert error: %v", err)
	}
	//defer kdb.DeletePubKeyInfo(deviceId)
}

func TestClientapiKeyOp(t *testing.T) {
	print("\nThis is in TestClientapiKeyOp\n")
	prepare()
	defer release()
	server := config.GetServerPort()
	go StartServer(server)
	defer StopServer()
	trustmgr.CreateTrustManager(constDB, constDNS)
	defer trustmgr.ReleaseTrustManager()
	regtime := time.Time{}
	trustmgr.RegisterClientByID(deviceId, regtime, ik)
	defer trustmgr.DeleteClientByID(deviceId)

	c, err := trustmgr.GetCache(deviceId)
	if err != nil {
		t.Errorf(constgetcachefailed, err)
	}
	c.UpdateHeartBeat(testCases1[0])
	c.UpdateTrustReport(testCases1[0])
	c.SetTaTrusted(ktaId, cache.StrTrusted)

	ras, err := CreateConn(server)
	if err != nil {
		t.Errorf("fail to Create connection %v", err)
	}
	defer ReleaseConn(ras)
	ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
	defer cancel()

	// generate public key and priate key of KCM
	privKey, kcmPublicKey := GenRsaKey()
	err = os.Mkdir(certPath, fileMod)
	assert.NoError(t, err)
	err = ioutil.WriteFile(certPath+kcmKeyName, []byte(privKey), keyMod)
	assert.NoError(t, err)

	// test empty taId
	_, err = ras.c.KeyOperation(ctx, &KeyOperationRequest{})
	if err != nil {
		t.Errorf("test KeyOperation with empty taId failed %v", err)
	}

	go kmsServer.ExampleServer()
	defer kmsServer.StopServer()

	kdb.CreateKdbManager(constDB, constDNS)
	defer kdb.ReleaseKdbManager()

	err = kcmstools.SaveCert(ktacert, certPath, ktaFileName)
	if err != nil {
		t.Errorf(constSaveKTACertFailed, err)
	}
	defer os.RemoveAll(certPath)
	base64_pubKey := base64.StdEncoding.EncodeToString(ktacert)
	_, err = kdb.SavePubKeyInfo(deviceId, base64_pubKey)
	if err != nil {
		t.Errorf("save public key in database failed, error: %v", err)
	}
	defer kdb.DeletePubKeyInfo(deviceId)

	_, err = kdb.SaveKeyInfo(string(taId), string(keyId), cipherMessage)
	if err != nil {
		t.Errorf("save key in database failed, error %v", err)
	}
	defer kdb.DeleteKeyInfo(string(taId), string(keyId))

	message := inKeyInfo{
		TAId:      taId,
		Account:   account,
		Password:  password,
		KeyId:     keyId,
		HostKeyId: hostKeyId,
		Command:   command,
		KTAId:     ktaId,
	}
	encMessage, err := json.Marshal(message)
	if err != nil {
		t.Errorf("Encode inside json of key operation error: %v", err)
	}

	sessionKey := make([]byte, 32)
	if _, err = io.ReadFull(rand.Reader, sessionKey); err != nil {
		t.Errorf("make session key error: %v", err)
	}

	// TODO: use decKey to encrypt encMessage as encCmdData
	cmdData, tag, nonce, err := aesGCMEncrypt(sessionKey, encMessage)
	if err != nil {
		t.Errorf("Encode AESGCM error: %v", err)
	}

	appendKey := append(nonce, sessionKey...)
	appendKey = append(appendKey, tag...)

	// TODO: use kcm public key to encrypt decKey as key
	key, err := RsaEncrypt(appendKey, kcmPublicKey)
	if err != nil {
		t.Errorf("Encode rsa error: %v", err)
	}

	encKey := hex.EncodeToString(key)
	encData := hex.EncodeToString(cmdData)

	decCmdData := tagCmdData{
		Key:        encKey,
		EncCmdData: encData,
	}
	outCmdData, err := json.Marshal(decCmdData)
	if err != nil {
		t.Errorf("Encode outside json of key operation error: %v", err)
	}

	_, err = ras.c.KeyOperation(ctx, &KeyOperationRequest{
		ClientId:   deviceId,
		EncMessage: outCmdData,
	})
	if err != nil {
		t.Errorf("test KeyOperation error %v", err)
	}
}

func TestDoClientapi(t *testing.T) {
	print("\nThis is in TestDoClientapi\n")
	trustmgr.CreateTrustManager(constDB, constDNS)
	defer trustmgr.ReleaseTrustManager()
	prepare()
	defer release()
	server := config.GetServerPort()

	go StartServer(server)
	defer StopServer()

	EKpubBlock, _ := pem.Decode([]byte(EKpubPEM))
	reqEC := GenerateEKCertRequest{EkPub: EKpubBlock.Bytes}
	rspEC, err := DoGenerateEKCert(server, &reqEC)
	if err != nil {
		t.Errorf("test DoGenerateEKCert error %v", err)
	}
	IKpubBlock, _ := pem.Decode([]byte(IKpubPEM))
	_, err = DoGenerateIKCert(server, &GenerateIKCertRequest{
		EkCert: rspEC.EkCert,
		IkPub:  IKpubBlock.Bytes,
		IkName: IKName,
	})
	if err != nil {
		t.Errorf("test DoGenerateIKCert error %v", err)
	}

	// test empty clientinfo
	ci, err := json.Marshal(map[string]string{})
	if err != nil {
		t.Error(emptyClientInfoErr)
	}
	r1, err := DoRegisterClient(server, &RegisterClientRequest{
		Cert:       createCert(),
		ClientInfo: string(ci),
	})
	if err != nil {
		t.Errorf("test DoRegisterClient with empty clientinfo error %v", err)
	}
	defer trustmgr.DeleteClientByID(r1.GetClientId())

	// test empty request
	_, err = DoRegisterClient(server, &RegisterClientRequest{})
	if err == nil {
		t.Errorf("test DoRegisterClient with empty request failed")
	}
	template := x509.Certificate{
		SerialNumber: big.NewInt(cryptotools.GetSerialNumber()),
		NotBefore:    time.Now(),
		NotAfter:     time.Now().AddDate(1, 0, 0),
		KeyUsage: x509.KeyUsageDigitalSignature |
			x509.KeyUsageKeyEncipherment | x509.KeyUsageCertSign,
		IsCA:           false,
		MaxPathLenZero: true,
		IPAddresses:    []net.IP{net.ParseIP(config.GetIP())},
	}
	ikCertDer, _ := cryptotools.GenerateCertificate(&template,
		config.GetPcaKeyCert(), IKpubBlock.Bytes, config.GetPcaPrivateKey())

	ci, err = json.Marshal(testClientInfo)
	if err != nil {
		t.Error(createClientInfoErr)
	}
	r2, err := DoRegisterClient(server, &RegisterClientRequest{
		Cert:       ikCertDer,
		ClientInfo: string(ci),
	})
	if err != nil {
		t.Errorf("test DoRegisterClient error %v", err)
	}

	// test empty clientId
	_, err = DoSendHeartbeat(server, &SendHeartbeatRequest{})
	if err != nil {
		t.Errorf("test DoSendHeartbeat with empty ClientId failed")
	}

	HBrep, err := DoSendHeartbeat(server, &SendHeartbeatRequest{ClientId: r2.GetClientId()})
	if err != nil {
		t.Errorf("test DoSendHeartbeat error %v", err)
	}

	// test empty report
	srRep, _ := DoSendReport(server, &SendReportRequest{})
	if srRep.GetResult() {
		t.Errorf("test DoSendReport with empty report failed")
	}

	testbios, err := ioutil.ReadFile(BIOSLogPath)
	if err != nil {
		t.Errorf("ReadFile error %v", err)
	}
	testima, err := ioutil.ReadFile(IMALogPath)
	if err != nil {
		t.Errorf("ReadFile error %v", err)
	}
	srRep, _ = DoSendReport(server, &SendReportRequest{
		ClientId:   r2.GetClientId(),
		Nonce:      HBrep.ClientConfig.Nonce,
		ClientInfo: string(ci),
		Quoted:     testquote,
		Signature:  testsignature,
		Manifests: []*Manifest{
			0: {Key: "pcr", Value: testpcr},
			1: {Key: "bios", Value: testbios},
			2: {Key: "ima", Value: testima},
		},
	})
	if !srRep.GetResult() {
		t.Errorf(sendrRportErr)
	}
	_, err = DoUnregisterClient(server, &UnregisterClientRequest{})
	if err != nil {
		t.Errorf("test DoUnregisterClient with empty clientId failed %v", err)
	}

	_, err = DoUnregisterClient(server, &UnregisterClientRequest{
		ClientId: r2.GetClientId(),
	})
	if err != nil {
		t.Errorf("test DoUnregisterClient error %v", err)
	}
	defer trustmgr.DeleteClientByID(r2.GetClientId())
	defer trustmgr.DeleteReportByID(r2.GetClientId())
}

func TestDoClientapiInitKTA(t *testing.T) {
	print("\nThis is in TestDoClientapiInitKTA\n")
	prepare()
	defer release()
	server := config.GetServerPort()
	go StartServer(server)
	defer StopServer()

	// test SendKCMPubKeyCert
	err := kcmstools.SaveCert([]byte(kcmCert), certPath, kcmFileName)
	if err != nil {
		t.Errorf("save KCM Cert failed, error: %v", err)
	}
	_, err = DoSendKCMPubKeyCert(server, &SendKCMPubKeyCertRequest{})
	if err != nil {
		t.Errorf("test SendKCMPubKeyCert failed %v", err)
	}

	// test empty deviceId
	_, err = DoVerifyKTAPubKeyCert(server, &VerifyKTAPubKeyCertRequest{})
	if err != nil {
		t.Errorf("test DoVerifyKTAPubKeyCert with empty deviceId failed %v", err)
	}

	//dbConfig := GetdbConfig(strDbConfig)
	//kdb.CreateKdbManager(constDB, dbConfig)
	//defer kdb.ReleaseKdbManager()

	err = kcmstools.SaveCert(ktacert, certPath, ktaFileName)
	if err != nil {
		t.Errorf(constSaveKTACertFailed, err)
	}
	err = kcmstools.SaveCert(rootcert, certPath, rootFileName)
	if err != nil {
		t.Errorf("save Root Cert failed, error: %v", err)
	}
	defer os.RemoveAll(certPath)
	_, err = DoVerifyKTAPubKeyCert(server, &VerifyKTAPubKeyCertRequest{
		ClientId:      deviceId,
		KtaPubKeyCert: ktacert,
	})
	if err != nil {
		t.Errorf("test VerifyKTAPubKeyCert error %v", err)
	}
	//defer kdb.DeletePubKeyInfo(deviceId)
}

func TestDoClientapiKeyOp(t *testing.T) {
	print("\nThis is in TestDoClientapiKeyOp\n")
	prepare()
	defer release()
	server := config.GetServerPort()
	go StartServer(server)
	defer StopServer()
	trustmgr.CreateTrustManager(constDB, constDNS)
	defer trustmgr.ReleaseTrustManager()
	regtime := time.Time{}
	trustmgr.RegisterClientByID(deviceId, regtime, ik)
	defer trustmgr.DeleteClientByID(deviceId)

	c, err := trustmgr.GetCache(deviceId)
	if err != nil {
		t.Errorf(constgetcachefailed, err)
	}
	c.UpdateHeartBeat(testCases1[0])
	c.UpdateTrustReport(testCases1[0])
	c.SetTaTrusted(ktaId, cache.StrTrusted)

	// generate public key and priate key of KCM
	privKey, kcmPublicKey := GenRsaKey()
	err = os.Mkdir(certPath, fileMod)
	assert.NoError(t, err)
	err = ioutil.WriteFile(certPath+kcmKeyName, []byte(privKey), keyMod)
	assert.NoError(t, err)

	// test empty taId
	_, err = DoKeyOperation(server, &KeyOperationRequest{})
	if err != nil {
		t.Errorf("test DoKeyOperation with empty taId failed %v", err)
	}

	go kmsServer.ExampleServer()
	defer kmsServer.StopServer()

	kdb.CreateKdbManager(constDB, constDNS)
	defer kdb.ReleaseKdbManager()

	err = kcmstools.SaveCert(ktacert, certPath, ktaFileName)
	if err != nil {
		t.Errorf(constSaveKTACertFailed, err)
	}
	defer os.RemoveAll(certPath)
	base64_pubKey := base64.StdEncoding.EncodeToString(ktacert)
	_, err = kdb.SavePubKeyInfo(deviceId, base64_pubKey)
	if err != nil {
		t.Errorf("save public key in database failed, error, %v", err)
	}
	defer kdb.DeletePubKeyInfo(deviceId)

	_, err = kdb.SaveKeyInfo(string(taId), string(keyId), cipherMessage)
	if err != nil {
		t.Errorf("save key in database failed, error: %v", err)
	}
	defer kdb.DeleteKeyInfo(string(taId), string(keyId))

	message := inKeyInfo{
		TAId:      taId,
		Account:   account,
		Password:  password,
		KeyId:     keyId,
		HostKeyId: hostKeyId,
		Command:   command,
		KTAId:     ktaId,
	}
	encMessage, err := json.Marshal(message)
	if err != nil {
		t.Errorf("Encode inside json of key operation error: %v", err)
	}

	sessionKey := make([]byte, 32)
	if _, err = io.ReadFull(rand.Reader, sessionKey); err != nil {
		t.Errorf("make session key error: %v", err)
	}

	// TODO: use decKey to encrypt encMessage as encCmdData
	cmdData, tag, nonce, err := aesGCMEncrypt(sessionKey, encMessage)
	if err != nil {
		t.Errorf("Encode AESGCM error: %v", err)
	}

	appendKey := append(nonce, sessionKey...)
	appendKey = append(appendKey, tag...)

	// TODO: use kcm public key to encrypt decKey as key
	key, err := RsaEncrypt(appendKey, kcmPublicKey)
	if err != nil {
		t.Errorf("Encode rsa error: %v", err)
	}

	encKey := hex.EncodeToString(key)
	encData := hex.EncodeToString(cmdData)

	decCmdData := tagCmdData{
		Key:        encKey,
		EncCmdData: encData,
	}
	outCmdData, err := json.Marshal(decCmdData)
	if err != nil {
		t.Errorf("Encode outside json of key operation error: %v", err)
	}

	_, err = DoKeyOperation(server, &KeyOperationRequest{
		ClientId:   deviceId,
		EncMessage: outCmdData,
	})
	if err != nil {
		t.Errorf("test KeyOperation error %v", err)
	}
}

func TestClientapiWithConn(t *testing.T) {
	print("\nThis is in TestClientapiWithConn\n")
	trustmgr.CreateTrustManager(constDB, constDNS)
	defer trustmgr.ReleaseTrustManager()
	prepare()
	defer release()
	server := config.GetServerPort()

	go StartServer(server)
	defer StopServer()

	ras, err := CreateConn(server)
	if err != nil {
		t.Errorf("fail to Create connection, %v", err)
	}
	defer ReleaseConn(ras)

	EKpubBlock, _ := pem.Decode([]byte(EKpubPEM))
	reqEC := GenerateEKCertRequest{
		EkPub: EKpubBlock.Bytes,
	}
	rspEC, err := DoGenerateEKCertWithConn(ras, &reqEC)
	if err != nil {
		t.Errorf("test DoGenerateEKCertWithConn error %v", err)
	}
	IKpubBlock, _ := pem.Decode([]byte(IKpubPEM))
	_, err = DoGenerateIKCertWithConn(ras, &GenerateIKCertRequest{
		EkCert: rspEC.EkCert,
		IkPub:  IKpubBlock.Bytes,
		IkName: IKName,
	})
	if err != nil {
		t.Errorf("test DoGenerateIKCertWithConn error %v", err)
	}

	// test empty clientinfo
	ci, err := json.Marshal(map[string]string{})
	if err != nil {
		t.Error(emptyClientInfoErr)
	}
	r1, err := DoRegisterClientWithConn(ras, &RegisterClientRequest{
		Cert:       createCert(),
		ClientInfo: string(ci),
	})
	if err != nil {
		t.Errorf("test DoRegisterClientWithConn with empty clientinfo error %v", err)
	}
	defer trustmgr.DeleteClientByID(r1.GetClientId())

	// test empty request
	_, err = DoRegisterClientWithConn(ras, &RegisterClientRequest{})
	if err == nil {
		t.Errorf("test DoRegisterClientWithConn with empty request failed")
	}
	template := x509.Certificate{
		SerialNumber: big.NewInt(cryptotools.GetSerialNumber()),
		NotBefore:    time.Now(),
		NotAfter:     time.Now().AddDate(1, 0, 0),
		KeyUsage: x509.KeyUsageDigitalSignature |
			x509.KeyUsageKeyEncipherment | x509.KeyUsageCertSign,
		IsCA:           false,
		MaxPathLenZero: true,
		IPAddresses:    []net.IP{net.ParseIP(config.GetIP())},
	}
	ikCertDer, _ := cryptotools.GenerateCertificate(&template,
		config.GetPcaKeyCert(), IKpubBlock.Bytes, config.GetPcaPrivateKey())

	ci, err = json.Marshal(testClientInfo)
	if err != nil {
		t.Error(createClientInfoErr)
	}
	r2, err := DoRegisterClientWithConn(ras, &RegisterClientRequest{
		Cert:       ikCertDer,
		ClientInfo: string(ci),
	})
	if err != nil {
		t.Errorf("test DoRegisterClientWithConn error %v", err)
	}
	_, err = DoSendHeartbeatWithConn(ras, &SendHeartbeatRequest{ClientId: r2.GetClientId()})
	if err != nil {
		t.Errorf("test DoSendHeartbeatWithConn error %v", err)
	}

	// test empty clientId
	_, err = DoSendHeartbeatWithConn(ras, &SendHeartbeatRequest{})
	if err != nil {
		t.Errorf("test SendHeartbeatWithConn with empty ClientId failed")
	}

	HBrep, err := DoSendHeartbeatWithConn(ras, &SendHeartbeatRequest{ClientId: r2.GetClientId()})
	if err != nil {
		t.Errorf("test SendHeartbeatWithConn error %v", err)
	}

	// test empty report
	srRep, _ := DoSendReportWithConn(ras, &SendReportRequest{})
	if srRep.GetResult() {
		t.Errorf("test DoSendReportWithConn with empty report failed")
	}

	testbios, err := ioutil.ReadFile(BIOSLogPath)
	if err != nil {
		t.Errorf("ReadFile error %v", err)
	}
	testima, err := ioutil.ReadFile(IMALogPath)
	if err != nil {
		t.Errorf("ReadFile error %v", err)
	}
	srRep, _ = DoSendReportWithConn(ras, &SendReportRequest{
		ClientId:   r2.GetClientId(),
		Nonce:      HBrep.ClientConfig.Nonce,
		ClientInfo: string(ci),
		Quoted:     testquote,
		Signature:  testsignature,
		Manifests: []*Manifest{
			0: {Key: "pcr", Value: testpcr},
			1: {Key: "bios", Value: testbios},
			2: {Key: "ima", Value: testima},
		},
	})
	if !srRep.GetResult() {
		t.Errorf(sendrRportErr)
	}

	// test empty clientId
	_, err = DoUnregisterClientWithConn(ras, &UnregisterClientRequest{})
	if err != nil {
		t.Errorf("test DoUnregisterClientWithConn with empty clientId failed %v", err)
	}

	_, err = DoUnregisterClientWithConn(ras, &UnregisterClientRequest{
		ClientId: r2.GetClientId(),
	})
	if err != nil {
		t.Errorf("test DoUnregisterClientWithConn error %v", err)
	}
	defer trustmgr.DeleteClientByID(r2.GetClientId())
	defer trustmgr.DeleteReportByID(r2.GetClientId())
}

func TestClientapiWithConnInitKTA(t *testing.T) {
	print("\nThis is in TestClientapiWithConnInitKTA\n")
	prepare()
	defer release()
	server := config.GetServerPort()
	go StartServer(server)
	defer StopServer()

	ras, err := CreateConn(server)
	if err != nil {
		t.Errorf("fail to Create connection: %v", err)
	}
	defer ReleaseConn(ras)

	// test SendKCMPubKeyCert
	err = kcmstools.SaveCert([]byte(kcmCert), certPath, kcmFileName)
	if err != nil {
		t.Errorf("save KCM Cert failed, error: %v", err)
	}
	_, err = DoSendKCMPubKeyCertWithConn(ras, &SendKCMPubKeyCertRequest{})
	if err != nil {
		t.Errorf("test SendKCMPubKeyCert failed %v", err)
	}

	// test empty deviceId
	_, err = DoVerifyKTAPubKeyCertWithConn(ras, &VerifyKTAPubKeyCertRequest{})
	if err != nil {
		t.Errorf("test DoVerifyKTAPubKeyCertWithConn with empty deviceId failed %v", err)
	}

	//dbConfig := GetdbConfig(strDbConfig)
	//kdb.CreateKdbManager(constDB, dbConfig)
	//defer kdb.ReleaseKdbManager()

	err = kcmstools.SaveCert(ktacert, certPath, ktaFileName)
	if err != nil {
		t.Errorf(constSaveKTACertFailed, err)
	}
	err = kcmstools.SaveCert(rootcert, certPath, rootFileName)
	if err != nil {
		t.Errorf("save Root Cert failed, error: %v", err)
	}
	defer os.RemoveAll(certPath)
	_, err = DoVerifyKTAPubKeyCertWithConn(ras, &VerifyKTAPubKeyCertRequest{
		ClientId:      deviceId,
		KtaPubKeyCert: ktacert,
	})
	if err != nil {
		t.Errorf("test VerifyKTAPubKeyCert error %v", err)
	}
	//defer kdb.DeletePubKeyInfo(deviceId)
}

func TestClientapiWithConnKeyOp(t *testing.T) {
	print("\nThis is in TestClientapiWithConnKeyOp\n")
	prepare()
	defer release()
	server := config.GetServerPort()
	go StartServer(server)
	defer StopServer()
	trustmgr.CreateTrustManager(constDB, constDNS)
	defer trustmgr.ReleaseTrustManager()
	regtime := time.Time{}
	trustmgr.RegisterClientByID(deviceId, regtime, ik)
	defer trustmgr.DeleteClientByID(deviceId)

	c, err := trustmgr.GetCache(deviceId)
	if err != nil {
		t.Errorf(constgetcachefailed, err)
	}
	c.UpdateHeartBeat(testCases1[0])
	c.UpdateTrustReport(testCases1[0])
	c.SetTaTrusted(ktaId, cache.StrTrusted)

	ras, err := CreateConn(server)
	if err != nil {
		t.Errorf("fail to Create connection: %v", err)
	}
	defer ReleaseConn(ras)

	// generate public key and priate key of KCM
	privKey, kcmPublicKey := GenRsaKey()
	err = os.Mkdir(certPath, fileMod)
	assert.NoError(t, err)
	err = ioutil.WriteFile(certPath+kcmKeyName, []byte(privKey), keyMod)
	assert.NoError(t, err)

	// test empty taId
	_, err = DoKeyOperationWithConn(ras, &KeyOperationRequest{})
	if err != nil {
		t.Errorf("test DoKeyOperationWithConn with empty taId failed %v", err)
	}

	go kmsServer.ExampleServer()
	defer kmsServer.StopServer()

	kdb.CreateKdbManager(constDB, constDNS)
	defer kdb.ReleaseKdbManager()

	err = kcmstools.SaveCert(ktacert, certPath, ktaFileName)
	if err != nil {
		t.Errorf(constSaveKTACertFailed, err)
	}
	defer os.RemoveAll(certPath)
	base64_pubKey := base64.StdEncoding.EncodeToString(ktacert)
	_, err = kdb.SavePubKeyInfo(deviceId, base64_pubKey)
	if err != nil {
		t.Errorf("save public key in database failed, error %v", err)
	}
	defer kdb.DeletePubKeyInfo(deviceId)

	_, err = kdb.SaveKeyInfo(string(taId), string(keyId), cipherMessage)
	if err != nil {
		t.Errorf("save key in database failed, error: %v", err)
	}
	defer kdb.DeleteKeyInfo(string(taId), string(keyId))

	message := inKeyInfo{
		TAId:      taId,
		Account:   account,
		Password:  password,
		KeyId:     keyId,
		HostKeyId: hostKeyId,
		Command:   command,
		KTAId:     ktaId,
	}
	encMessage, err := json.Marshal(message)
	if err != nil {
		t.Errorf("Encode inside json of key operation error: %v", err)
	}

	sessionKey := make([]byte, 32)
	if _, err = io.ReadFull(rand.Reader, sessionKey); err != nil {
		t.Errorf("make session key error: %v", err)
	}

	// TODO: use decKey to encrypt encMessage as encCmdData
	cmdData, tag, nonce, err := aesGCMEncrypt(sessionKey, encMessage)
	if err != nil {
		t.Errorf("Encode AESGCM error: %v", err)
	}

	appendKey := append(nonce, sessionKey...)
	appendKey = append(appendKey, tag...)

	// TODO: use kcm public key to encrypt decKey as key
	key, err := RsaEncrypt(appendKey, kcmPublicKey)
	if err != nil {
		t.Errorf("Encode rsa error: %v", err)
	}

	encKey := hex.EncodeToString(key)
	encData := hex.EncodeToString(cmdData)

	decCmdData := tagCmdData{
		Key:        encKey,
		EncCmdData: encData,
	}
	outCmdData, err := json.Marshal(decCmdData)
	if err != nil {
		t.Errorf("Encode outside json of key operation error: %v", err)
	}

	_, err = DoKeyOperationWithConn(ras, &KeyOperationRequest{
		ClientId:   deviceId,
		EncMessage: outCmdData,
	})
	if err != nil {
		t.Errorf("test DoKeyOperationWithConn error %v", err)
	}
}

func createCert() []byte {
	max := new(big.Int).Lsh(big.NewInt(1), 128)
	serialNumber, err := rand.Int(rand.Reader, max)
	if err != nil {
		return nil
	}
	subject := pkix.Name{
		Organization: []string{"Company"},
		Country:      []string{"China"},
		CommonName:   "test ekcert",
	}

	Template := x509.Certificate{
		SerialNumber: serialNumber,
		Subject:      subject,
		NotBefore:    time.Now(),
		NotAfter:     time.Now().AddDate(10, 0, 0),
		KeyUsage:     x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment | x509.KeyUsageCertSign,
		ExtKeyUsage:  []x509.ExtKeyUsage{x509.ExtKeyUsageAny},
	}
	key, err := rsa.GenerateKey(rand.Reader, 2048)
	if err != nil {
		return nil
	}
	cert, err := x509.CreateCertificate(rand.Reader, &Template, &Template, &key.PublicKey, key)
	if err != nil {
		return nil
	}
	return cert
}

func RemoveFiles() {
	err := os.Remove("./pca-root.crt")
	if err != nil {
		return
	}
	err1 := os.Remove("./pca-root.key")
	if err1 != nil {
		return
	}
	err2 := os.Remove("./pca-ek.crt")
	if err2 != nil {
		return
	}
	err3 := os.Remove("./pca-ek.key")
	if err3 != nil {
		return
	}
	err4 := os.Remove("./https.crt")
	if err4 != nil {
		return
	}
	err5 := os.Remove("./https.key")
	if err5 != nil {
		return
	}
}

func GenRsaKey() (prvkey, pubkey []byte) {
	// 生成私钥文件
	privateKey, err := rsa.GenerateKey(rand.Reader, 2048)
	if err != nil {
		panic(err)
	}
	derStream := x509.MarshalPKCS1PrivateKey(privateKey)
	block := &pem.Block{
		Type:  "RSA PRIVATE KEY",
		Bytes: derStream,
	}
	prvkey = pem.EncodeToMemory(block)
	publicKey := &privateKey.PublicKey
	derPkix, err := x509.MarshalPKIXPublicKey(publicKey)
	if err != nil {
		panic(err)
	}
	block = &pem.Block{
		Type:  "PUBLIC KEY",
		Bytes: derPkix,
	}
	pubkey = pem.EncodeToMemory(block)
	return
}
*/
